理解“ is”操作符

is运算符与变量的值不匹配,但 实例本身。

这到底意味着什么?

我声明了两个名为 xy的变量,它们在两个变量中分配相同的值,但是当我使用 is操作符时,返回 false。

我需要澄清一下,这是我的代码。

x = [1, 2, 3]
y = [1, 2, 3]


print(x is y)  # It prints false!
95158 次浏览

You misunderstood what the is operator tests. It tests if two variables point the 同样的东西, not if two variables have the same value.

根据 is接线员的文件:

操作符 isis not测试对象标识: 当且仅当 xy是同一个对象时,x is y为 true。

改为使用 ==操作符:

print(x == y)

这个打印 Truexy是两个 分开列表:

x[0] = 4
print(y)  # prints [1, 2, 3]
print(x == y)   # prints False

如果你使用 id()功能,你会看到 xy有不同的标识符:

>>> id(x)
4401064560
>>> id(y)
4401098192

but if you were to assign y to x then both point to the same object:

>>> x = y
>>> id(x)
4401064560
>>> id(y)
4401064560
>>> x is y
True

is显示两者是同一个对象,它返回 True

Remember that in Python, 名称只是引用值的标签; you can have multiple names point to the same object. is tells you if two names point to one and the same object. == tells you if two names refer to objects that have the same value.

X 指向一个数组,Y 指向另一个数组。这些数组是相同的,但是 is操作符将查看那些不相同的指针。

它比较对象标识,即变量是否引用内存中的同一个对象。它类似于 Java 或 C 中的 ==(当比较指针时)。

正如你可以在这里检查到一个小整数。大于257的数字不是小整数,因此它是作为一个不同的对象计算的。

在这种情况下,最好使用 ==

进一步的信息在这里: http://docs.python.org/2/c-api/int.html

只有当它们实际上是相同的对象时,is才返回 true。如果它们是相同的,对其中一个的改变也会出现在另一个中。这里有一个差异的例子。

>>> x = [1, 2, 3]
>>> y = [1, 2, 3]
>>> print x is y
False
>>> z = y
>>> print y is z
True
>>> print x is z
False
>>> y[0] = 5
>>> print z
[5, 2, 3]

重复的问题的提示下,这种类比可能有效:

# - Darling, I want some pudding!
# - There is some in the fridge.


pudding_to_eat = fridge_pudding
pudding_to_eat is fridge_pudding
# => True


# - Honey, what's with all the dirty dishes?
# - I wanted to eat pudding so I made some. Sorry about the mess, Darling.
# - But there was already some in the fridge.


pudding_to_eat = make_pudding(ingredients)
pudding_to_eat is fridge_pudding
# => False

另一个重复的 是问为什么两个相等的字符串通常不相同,这里没有真正回答:

>>> x = 'a'
>>> x += 'bc'
>>> y = 'abc'
>>> x == y
True
>>> x is y
False

那么,为什么它们不是同一个字符串呢? 特别是考虑到:

>>> z = 'abc'
>>> w = 'abc'
>>> z is w
True

让我们把第二部分推迟一会儿。第一部分怎么可能是真的呢?

解释器必须有一个“实习表”,一个将字符串值映射到字符串对象的表,因此每次尝试创建一个包含内容 'abc'的新字符串时,都会返回相同的对象。Wikipedia有一个更详细的关于实习如何工作的讨论。

Python 已经是一个字符串实习表; 您可以使用 sys.intern方法手动实习字符串。

实际上,Python 是 允许自动实现任何不可变类型的内存,而不是 需要。不同的实现将实现不同的价值观。

CPython (如果你不知道你使用的是哪个实现的话,你正在使用的实现)自动实习小整数和一些特殊的单例例如 False,但不是字符串(或者大整数,或者小元组,或者其他任何东西)。你可以很容易地看到这一点:

>>> a = 0
>>> a += 1
>>> b = 1
>>> a is b
True
>>> a = False
>>> a = not a
>>> b = True
a is b
True
>>> a = 1000
>>> a += 1
>>> b = 1001
>>> a is b
False

但是为什么 zw是一样的呢?

这不是解释器自动实现,而是编译器折叠值。

如果同一个编译时字符串在同一个模块中出现两次(这意味着什么很难定义ーー它与字符串文字不是一回事,因为 r'abc''abc''a' 'b' 'c'都是不同的文字但是是同一个字符串ーー但是直观地很容易理解) ,编译器将只创建字符串的一个实例和两个引用。

事实上,编译器还可以更进一步: 优化器可以将 'ab' + 'c'转换为 'abc',在这种情况下,它可以与同一模块中的 'abc'常量折叠在一起。

同样,这是 Python 允许但不被要求做的事情。但是在这种情况下,CPython 总是折叠小字符串(以及小元组)。(尽管交互式解释器的逐条语句编译器不会运行与逐条模块编译器相同的优化,所以交互式地看不到完全相同的结果。)


那么,作为一个程序员,您应该如何处理这个问题呢?

没什么。您几乎没有任何理由去关心两个不可变的值是否相同。如果你想知道什么时候可以使用 a is b而不是 a == b,那你就问错问题了。除了以下两种情况,一定要使用 a == b:

  • 以便与单例值(如 x is None)进行更易读的比较。
  • 对于可变值,当需要知道突变 x是否会影响 y时。

isis not是 Python 中的两个标识运算符。is运算符不比较变量的值,而是比较变量的恒等式。想想这个:

>>> a = [1,2,3]
>>> b = [1,2,3]
>>> hex(id(a))
'0x1079b1440'
>>> hex(id(b))
'0x107960878'
>>> a is b
False
>>> a == b
True
>>>

上面的例子显示了身份(也可以是 Cpython 的内存地址)对于 ab是不同的(即使它们的值是相同的)。这就是为什么当你说 a is b时,由于两个操作数的标识不匹配,它返回 false。但是,当您说 a == b时,它将返回 true,因为 ==操作只验证两个操作数是否分配了相同的值。

有趣的例子(对于额外的成绩) :

>>> del a
>>> del b
>>> a = 132
>>> b = 132
>>> hex(id(a))
'0x7faa2b609738'
>>> hex(id(b))
'0x7faa2b609738'
>>> a is b
True
>>> a == b
True
>>>

在上面的例子中,尽管 ab是两个不同的变量,但是 a is b返回了 True。这是因为 a的类型是 int,这是一个不可变物件。因此,python (我猜想是为了节省内存)在创建具有相同值的 b时将相同的对象分配给它。所以在这个例子中,变量的恒等式是匹配的,结果 a is bTrue

这将适用于所有不可变对象:

>>> del a
>>> del b
>>> a = "asd"
>>> b = "asd"
>>> hex(id(a))
'0x1079b05a8'
>>> hex(id(b))
'0x1079b05a8'
>>> a is b
True
>>> a == b
True
>>>

Hope that helps.

x is yid(x) == id(y)相同,比较对象的标识。

正如@tomasz-kurgan 在下面的注释中指出的那样,is操作符对某些对象的行为异常。

E.g.

>>> class A(object):
...   def foo(self):
...     pass
...
>>> a = A()
>>> a.foo is a.foo
False
>>> id(a.foo) == id(a.foo)
True

参考文献;
Https://docs.python.org/2/reference/expressions.html#is-not
https://docs.python.org/2/reference/expressions.html#id24

一个水果的简单例子

fruitlist = [" apple ", " banana ", " cherry ", " durian "]
newfruitlist = fruitlist
verynewfruitlist = fruitlist [:]
print ( fruitlist is newfruitlist )
print ( fruitlist is verynewfruitlist )
print ( newfruitlist is verynewfruitlist )

产出:

True
False
False

如果你尝试

fruitlist = [" apple ", " banana ", " cherry ", " durian "]
newfruitlist = fruitlist
verynewfruitlist = fruitlist [:]
print ( fruitlist == newfruitlist )
print ( fruitlist == verynewfruitlist )
print ( newfruitlist == verynewfruitlist )

结果是不同的:

True
True
True

这是因为 = = 运算符只比较变量的内容。要比较2个变量的恒等式,可以使用 运算符

打印身份证号码:

print ( id( variable ) )

is操作符只不过是 ==的英文版本。 因为两个列表的 ID 不同,所以答案是假的。 你可以试试:

a=[1,2,3]
b=a
print(b is a )#True

*Because the IDs of both the list would be same