奇怪的结果在python中

pyr*_*rou 7 python string identity

有人可以在python 2.6.6上解释我这个奇怪的结果吗?

>>> a = "xx"
>>> b = "xx"
>>> a.__hash__() == b.__hash__()
True
>>> a is b
True # ok.. was just to be sure

>>> a = "x" * 2
>>> b = "x" * 2
>>> a.__hash__() == b.__hash__()
True
>>> a is b
True # yeah.. looks ok so far !

>>> n = 2
>>> a = "x" * n
>>> b = "x" * n
>>> a.__hash__() == b.__hash__()
True # still okay..
>>> a is b
False # hey! What the F... ?
Run Code Online (Sandbox Code Playgroud)

Kat*_*iel 18

is运营商告诉你两个变量是否指向内存中的同一个对象.它很少有用,经常与==操作员混淆,后者告诉您两个对象是否"看起来相同".

当与短字符串文字这样的东西一起使用时,它尤其令人困惑,因为Python编译器为了提高效率而实现了这些.换句话说,当你编写"xx"编译器(发出字节码)在内存中创建一个字符串对象并导致所有文字"xx"指向它.这就解释了为什么你的前两个比较是真的.请注意,您可以通过调用id它们来获取字符串的id ,(至少在CPython上可能)它们在内存中的地址:

>>> a = "xx"
>>> b = "xx"
>>> id(a)
38646080
>>> id(b)
38646080
>>> a is b
True
>>> a = "x"*10000
>>> b = "x"*10000
>>> id(a)
38938560
>>> id(b)
38993504
>>> a is b
False
Run Code Online (Sandbox Code Playgroud)

第三是因为编译器没有拘留弦ab,无论出于何种原因(可能是因为它是不是足够聪明,该变量n定义一次,然后永远不会被修改).

您可以在事实上力Python来实习生串通过,那么,要求它.这将为您提供大量的性能提升,并可能会有所帮助.它可能没用.

道德:不要使用is字符串文字.或者是int literals.或者在任何你不理解的地方,真的.


Gle*_*ard 12

要理解这一点,您需要了解一些不同的东西.

  • a is b如果ab同一个对象,则返回true ,而不仅仅是它们具有相同的值.字符串可以具有相同的值,但可以是该值的不同实例.
  • 当你说a = "x",你实际在做的是创建一个字符串常量"x",然后为它指定一个名字,a.字符串常量是字面上在代码中写入的字符串,不是以编程方式计算的.字符串常量总是被实现,这意味着它们存储在一个表中以供重用:如果你说a = "a"; b = "a",它实际上与说法相同a = "a"; b = a,因为它们将使用相同的实习字符串"a".这就是为什么第一个a is b是真的.
  • 当你说a = "x" * 2,Python编译器实际上正在优化它.它在编译时计算字符串 - 它生成的代码就像你写的一样a = "xx".因此,结果字符串"xx'被实现.这就是为什么第二个a is b是真的.
  • 当你说a = "x" * n,Python编译器在编译时不知道n是什么.因此,它必须实际输出字符串"x",然后在运行时执行字符串乘法.因为这是在运行时执行,而"x"被拘留得到的字符串"xx"不是.因此,这些字符串中的每一个都是不同的实例"xx",因此最终的结果a is b为False.

你可以自己看出差异:

def a1():
    a = "x"
def a2():
    a = "x" * 2
def a3():
    n = 2
    a = "x" * n


import dis
print "a1:"
dis.dis(a1)

print "a2:"
dis.dis(a2)

print "a3:"
dis.dis(a3)
Run Code Online (Sandbox Code Playgroud)

在CPython 2.6.4中,这输出:

a1:
  4           0 LOAD_CONST               1 ('x')
              3 STORE_FAST               0 (a)
              6 LOAD_CONST               0 (None)
              9 RETURN_VALUE
a2:
  6           0 LOAD_CONST               3 ('xx')
              3 STORE_FAST               0 (a)
              6 LOAD_CONST               0 (None)
              9 RETURN_VALUE
a3:
  8           0 LOAD_CONST               1 (2)
              3 STORE_FAST               0 (n)

  9           6 LOAD_CONST               2 ('x')
              9 LOAD_FAST                0 (n)
             12 BINARY_MULTIPLY
             13 STORE_FAST               1 (a)
             16 LOAD_CONST               0 (None)
             19 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)

最后,请注意,a = intern(a); b = intern(b)如果字符串,您可以说创建实习版本,这将保证a is b是真的.如果您只想检查字符串相等性,那么只需使用a == b.