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"分配给xy

由于string是不可变的,因此解释器只需要存储一次string,并将所有variables指向同一个对象。
因此,你看到的ID是相同的。

在情况2中,您正在使用连接来修改xxy都具有相同的值,但不具有相同的身份。
两者都指向内存中的不同对象。 因此他们有不同的idis运算符返回False