是运算符比较两个对象的内存地址是否相同,则返回true否则返回false。 代码#1是运算符混淆
>>a="poi"
>>b="poi"
a is b
true
我已经创建了两个对象,其内容是相同的,但它们是在不同的内存地址的整个生活。 那么为什么操作符返回true?它不应该返回错误。 就像这个代码
>>ktr = "today is a fine day"
>>ptr = "today is a fine day"
>>ktr is ptr
false
是运算符比较两个对象的内存地址是否相同,则返回true否则返回false。 代码#1是运算符混淆
>>a="poi"
>>b="poi"
a is b
true
我已经创建了两个对象,其内容是相同的,但它们是在不同的内存地址的整个生活。 那么为什么操作符返回true?它不应该返回错误。 就像这个代码
>>ktr = "today is a fine day"
>>ptr = "today is a fine day"
>>ktr is ptr
false
我认为它与string interning.有关。本质上,其思想是仅存储每个不同字符串的单个副本,以提高某些操作的性能。
基本上,a is b
工作的原因是因为(正如您可能已经猜到的那样),在这两种情况下都有Python引用的单个不可变字符串。当一个字符串很大(以及其他一些我不明白的因素时,很可能),这不会完成,这就是为什么您的第二个示例返回False。
编辑:而事实上,奇怪的行为似乎是互动环境的副作用。如果您将相同的代码放入Python脚本中,则a is b
和ktr is ptr
都会返回True。
a="poi"
b="poi"
print a is b # Prints 'True'
ktr = "today is a fine day"
ptr = "today is a fine day"
print ktr is ptr # Prints 'True'
这很有道理,因为Python可以很容易地解析源文件并在其中查找重复的字符串文字。如果您动态创建字符串,则即使在脚本中它的行为也不同。
a="p" + "oi"
b="po" + "i"
print a is b # Oddly enough, prints 'True'
ktr = "today is" + " a fine day"
ptr = "today is a f" + "ine day"
print ktr is ptr # Prints 'False'
至于为什么a is b
仍然导致真,也许分配的字符串足够小,以保证通过实习集合的快速搜索,而另一种是不?
关于'a =“p”+“oi”; b =“po”+“i”',编译器通过在代码对象中存储两个对''poi''的引用来优化简单字符串连接,这些引用被放置在适当位置。 ''今天是一个美好的一天“'因为它包含空格(即非名字符)而没有被实施。 – eryksun
is
是身份鉴定。它将工作在更小的某些字符串(因为缓存)而不是更大的其他字符串。由于str不是ptr。 [感谢erykson]
参见此代码:
>>> import dis
>>> def fun():
... str = 'today is a fine day'
... ptr = 'today is a fine day'
... return (str is ptr)
...
>>> dis.dis(fun)
2 0 LOAD_CONST 1 ('today is a fine day')
3 STORE_FAST 0 (str)
3 6 LOAD_CONST 1 ('today is a fine day')
9 STORE_FAST 1 (ptr)
4 12 LOAD_FAST 0 (str)
15 LOAD_FAST 1 (ptr)
18 COMPARE_OP 8 (is)
21 RETURN_VALUE
>>> id(str)
26652288
>>> id(ptr)
27604736
#hence this comparison returns false: ptr is str
通知str
和ptr
的ID不同。
BUT:x和y的
>>> x = "poi"
>>> y = "poi"
>>> id(x)
26650592
>>> id(y)
26650592
#hence this comparison returns true : x is y
ID相同。因此,is
运算符工作在“ids”而不是“equalities”上
请参阅下面的链接,了解python何时和为什么会为相同的字符串分配不同的内存位置(也请阅读该问题)。在python2.x
When does python allocate new memory for identical strings
而且sys.intern
上python3.x和intern
应该帮助你分配的字符串相同的内存位置,该字符串的大小无关。
is
是不是与==
相同。
基本上,is
检查两个对象是否相同,而==
比较这些对象(字符串,如python中的所有内容,都是对象)的值。
所以你应该使用is
当你真的知道你正在看什么对象(即你已经做出了对象,或者正在与None
作为问题评论指出)比较,你想知道是否两个变量在内存中引用完全相同的对象。
然而,在您的示例中,您正在查看Python正在幕后处理的str
对象,因此,如果不深入研究python的工作原理,您就不会真正了解期望的结果。您会遇到与int
s或float
s相同的问题。其他答案在解释“幕后”内容(字符串实习)方面做得很好,但在日常编程中你大多不应该担心。
那么为什么这两个例子不同呢?这不解释。 – agf
@agf刚刚编辑 - 这是否解释我的意思是我的回答更好? –
请注意,这是CPython特定的优化。如果你想要你的代码是可移植的,你应该避免它。例如,在PyPy
>>>> a = "hi"
>>>> b = "hi"
>>>> a is b
False
另外值得指出的是,类似的事情发生了小整数
>>> a = 12
>>> b = 12
>>> a is b
True
再次你不应该依赖,因为其他的实现可能不包含这种优化。
在实践中,除非你正在做一些相当复杂的事情,否则你可能永远不会使用'is'。大概需要'=='来进行大多数的相等比较。 – dkamins
@dkamins:测试'None'的推荐方法是'':'some_var是None'(因为只有一个'None'的实例)。我会说这是一个很常见的情况。 – voithos
@voithos真的 - 我一直都在使用它(而不是'''),甚至没有想到它!但除此之外...... – dkamins