了解Python的“is”运算符
is
运算符不匹配变量的值,而是实例本身。
这是什么意思?
我声明了两个名为x
和y
的变量,在两个变量中赋值相同,但是当我使用is
运算符时,它返回false。
我需要澄清。 这是我的代码。
x = [1, 2, 3] y = [1, 2, 3] print x is y #It prints false!
你误会了什么is
运营商测试。 它测试两个变量是否指向相同的对象 ,而不是两个变量具有相同的值。
从is
运算符的文档:
运算符
is
,is not
测试对象的身份:当且仅当x
和y
是同一个对象时,x is y
是真的。
改为使用==
运算符:
print x == y
这打印True
。 x
和y
是两个单独的列表:
x[0] = 4 print y # prints [1, 2, 3] print x == y # prints False
如果你使用id()
函数,你会看到x
和y
有不同的标识符:
>>> id(x) 4401064560 >>> id(y) 4401098192
但是如果你将y
赋给x
那么它们都指向同一个对象:
>>> x = y >>> id(x) 4401064560 >>> id(y) 4401064560 >>> x is y True
并显示两者是相同的对象,则返回True
。
另一个重复的问是为什么两个相等的字符串通常是不相同的,这不是真的在这里回答:
>>> x = 'a' >>> x += 'bc' >>> y = 'abc' >>> x == y True >>> x is y False
那么,他们为什么不是同一个字符串呢? 特别是给了这个:
>>> z = 'abc' >>> w = 'abc' >>> z is w True
我们暂时放下第二部分。 第一个怎么可能是真的?
解释器必须有一个“实际表”(一个将字符串值映射到字符串对象的表),所以每次尝试创建一个带有'abc'
内容的新字符串时,都会返回相同的对象。 维基百科有关如何实习的更详细的讨论。
而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
好的,但为什么z
和w
相同?
这不是解释器自动实习,这是编译器折叠值。
如果相同的编译时字符串在同一个模块中出现两次(这意味着什么是难以定义的 – 它不是一个字符串文字,因为r'abc'
, 'abc'
和'a' 'b' 'c'
r'abc'
'a' 'b' 'c'
是所有不同的文字,但是相同的字符串,但直观易懂),编译器将只创建一个字符串实例,带有两个引用。
事实上,编译器可以更进一步:优化器可以将'ab' + 'c'
转换为'abc'
,在这种情况下,它可以与同一个模块中的'abc'
常量一起折叠。
再一次,这是Python允许的,但不是必须的。 但是在这种情况下,CPython总是折叠小的字符串(也是小的元组)。 (尽管交互式解释程序的声明式语句编译器并不像“一次一个模块”编译程序那样运行相同的优化,所以交互式地看不到完全相同的结果。)
那么,作为程序员,你应该怎么做呢?
呃…什么都没有 如果两个不可变的值是相同的,那么几乎没有任何理由关心。 如果你想知道什么时候可以使用a is b
而不是a == b
,那么你问的是错误的问题。 只是总是使用a == b
除了两种情况:
- 为了更多的可读性的比较,像
x is None
这样的单例值x is None
。 - 对于可变值,当你需要知道变异
x
是否会影响y
。
只有当它们实际上是同一个对象时才返回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
is
和is 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 >>>
上面的例子显示了a
和b
(即使它们的值相同)身份(也可以是Cpython中的内存地址)是不同的。 这就是为什么当你说a is b
,由于两个操作数的身份不匹配,它会返回错误。 然而,当你说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 >>>
在上面的例子中,即使a
和b
是两个不同的变量, a is b
返回True
。 这是因为a的类型是int
,它是一个不可变的对象。 所以Python(我想保存内存)分配相同的对象时,它是用相同的值创建。 所以在这种情况下,匹配的变量的身份和a is b
证明是True
。
这将适用于所有不可变对象:
>>> del a >>> del b >>> a = "asd" >>> b = "asd" >>> hex(id(a)) '0x1079b05a8' >>> hex(id(b)) '0x1079b05a8' >>> a is b True >>> a == b True >>>
希望有所帮助。
x is y
与id(x) == id(y)
,比较对象的标识。
X指向一个数组,Y指向一个不同的数组。 那些数组是相同的,但是is
运算符会查看那些不相同的指针。
正如你可以在这里检查一个小整数。 高于257的数字不是一个小数,所以它被计算为一个不同的对象。
在这种情况下,最好使用==
。
更多的信息在这里: http : //docs.python.org/2/c-api/int.html
它比较对象标识,也就是变量是否指向内存中的同一个对象。 这就像Java或C中的==
(当比较指针时)。