虽然这个问题在实践中没有任何实际用途,但我很好奇Python如何进行字符串实习。我注意到以下内容。
>> "string" is "string"
>> True
这是我所期待的。
你也可以这样做。
>> "strin"+"g" is "string"
>> True
这非常聪明!
但你不能这样做。
>> s1 = "strin"
>> s2 = "string"
>> s1+"g" is s2
>> False
为什么Python不会评估s1+"g"
,并意识到它与s1
相同并将其指向同一地址?在最后一个块中实际发生了什么让它返回False
?
这是特定于实现的,但您的解释器可能是实时编译时常量,但不是运行时表达式的结果。
接下来我使用CPython 2.7.3。
在第二个示例中,表达式"strin"+"g"
在编译时计算,并替换为"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()
第三个表达式的结果,您将得到与以前相同的对象:
>>> 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中,您已将字符串文字"123"
分配给x
和y
。
由于字符串是不可变的,因此解释器只将字符串文字存储一次并将所有变量指向同一个对象是有意义的。 因此,您将ID视为相同。
在案例2中,您正在使用串联修改x
。 x
和y
都具有相同的值,但身份不同。
两者都指向内存中的不同对象。因此他们有不同的id
和is
操作员返回False