Pythonstringinterning
虽然这个问题在实践中没有任何实际的用处,但我对Python如何实现string实习感到好奇。 我注意到以下。
>> "string" is "string" >> True
这正如我所料。
你也可以做到这一点。
>> "strin"+"g" is "string" >> True
这很聪明!
但是你不能这样做。
>> s1 = "strin" >> s2 = "string" >> s1+"g" is s2 >> False
为什么Python不会评估s1+"g"
,意识到它和s1
一样,并指向相同的地址? 在最后一个模块中实际发生的事情是否返回False
?
这是特定于实现的,但是解释器可能是编译时常量,而不是运行时expression式的结果。
在下面我使用CPython 2.7.3。
在第二个例子中,expression式"strin"+"g"
在编译时被评估,并被replace为"string"
。 这使前两个例子的行为相同。
如果我们检查字节码,我们会看到它们是完全一样的:
# s1 = "string" 2 0 LOAD_CONST 1 ('string') 3 STORE_FAST 0 (s1) # s2 = "strin" + "g" 3 6 LOAD_CONST 4 ('string') 9 STORE_FAST 1 (s2)
第三个例子涉及一个运行时连接,其结果不会自动实现:
# s3a = "strin" # s3 = s3a + "g" 4 12 LOAD_CONST 2 ('strin') 15 STORE_FAST 2 (s3a) 5 18 LOAD_FAST 2 (s3a) 21 LOAD_CONST 3 ('g') 24 BINARY_ADD 25 STORE_FAST 3 (s3) 28 LOAD_CONST 0 (None) 31 RETURN_VALUE
如果你要手工intern()
第三个expression式的结果,你会得到和以前一样的对象:
>>> s3a = "strin" >>> s3 = s3a + "g" >>> s3 is "string" False >>> intern(s3) is "string" True
情况1
>>> x = "123" >>> y = "123" >>> x == y True >>> x is y True >>> id(x) 50986112 >>> id(y) 50986112
案例2
>>> x = "12" >>> y = "123" >>> x = x + "3" >>> x is y False >>> x == y True
现在,你的问题是为什么id在情况1中是相同的,而不是在情况2中。
在情况1中,您已将string文字"123"
分配给x
和y
。
由于string是不可变的,因此解释器只需要存储一次string,并将所有variables指向同一个对象。
因此,你看到的ID是相同的。
在情况2中,您正在使用连接来修改x
。 x
和y
都具有相同的值,但不具有相同的身份。
两者都指向内存中的不同对象。 因此他们有不同的id
, is
运算符返回False