7

The is operator compares the memory addresses of two objects, and returns True if they're the same. Why, then, does it not work reliably with strings? Code #1

>>> a = "poi"
>>> b = "poi"
>>> a is b
True

Code #2

>>> ktr = "today is a fine day"
>>> ptr = "today is a fine day"
>>> ktr is ptr
False

I have created two strings whose content is the same but they are living on different memory addresses. Why is the output of the is operator not consistent?

4

4 回答 4

6

我相信这与字符串实习有关。本质上,这个想法是只存储每个不同字符串的一个副本,以提高某些操作的性能。

基本上,工作的原因a is b是因为(正如您可能已经猜到的)在这两种情况下,Python 都引用了一个不可变的字符串。当一个字符串很大时(很可能还有一些我不理解的其他因素),这没有完成,这就是你的第二个示例返回 False 的原因。

编辑:事实上,奇怪的行为似乎是交互环境的副作用。如果您使用相同的代码并将其放入 Python 脚本中,则两者都a is b返回ktr is ptrTrue。

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仍然导致 True,也许分配的字符串小到足以保证快速搜索实习集合,而另一个不是?

于 2012-10-25T05:38:23.900 回答
3

is是身份测试。它适用于较小的某些字符串(因为缓存),但不适用于较大的其他字符串。由于 str 不是 ptr。[感谢埃克森]

请参阅此代码:

>>> 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

注意IDstr注意和ptr不同。

但:

>>> x = "poi"
>>> y = "poi"
>>> id(x)
26650592
>>> id(y)
26650592
#hence this comparison returns true : x is y

x 和 y 的 ID 相同。因此is,运算符在“ids”上工作,而不是在“equalities”上工作

有关 python 何时以及为什么会为相同的字符串分配不同的内存位置的讨论,请参见下面的链接(也请阅读问题)。

python什么时候为相同的字符串分配新内存

同样sys.intern在 python3.x 和internpython2.x 上,应该可以帮助您将字符串分配到相同的内存位置,而不管字符串的大小。

于 2012-10-25T05:33:17.853 回答
2

is不一样。_==

基本上,is检查两个对象是否相同,同时==比较这些对象的值(字符串,就像 python 中的所有东西一样,都是对象)。

因此,is当您真正知道您正在查看的对象时(即,您已经制作了对象,或者正在与None问题评论指出的进行比较),并且您想知道两个变量是否引用完全相同时,您应该使用内存中的对象

但是,在您的示例中,您正在查看strpython 在幕后处理的对象,因此如果不深入了解 python 的工作原理,您真的不知道会发生什么。ints 或s会有同样的问题float。其他答案很好地解释了“幕后”的东西(字符串实习),但您在日常编程中大多不必担心它。

于 2012-10-25T05:34:36.313 回答
1

请注意,这是 CPython 特定的优化。如果你希望你的代码是可移植的,你应该避免它。例如,在 PyPy

>>>> a = "hi"
>>>> b = "hi"
>>>> a is b
False

还值得指出的是,小整数也会发生类似的事情

>>> a = 12
>>> b = 12
>>> a is b
True

您也不应该依赖它,因为其他实现可能不包括此优化。

于 2012-10-25T06:26:01.063 回答