Ze'*_*v G 80 python string internals
虽然这个问题在实践中没有任何实际用途,但我很好奇Python如何进行字符串实习.我注意到以下内容.
>> "string" is "string"
>> True
Run Code Online (Sandbox Code Playgroud)
这是我所期待的.
你也可以这样做.
>> "strin"+"g" is "string"
>> True
Run Code Online (Sandbox Code Playgroud)
这非常聪明!
但你不能这样做.
>> s1 = "strin"
>> s2 = "string"
>> s1+"g" is s2
>> False
Run Code Online (Sandbox Code Playgroud)
为什么Python不会评估s1+"g"
,意识到它是相同的s1
并指向同一个地址?在最后一个块中实际发生了什么让它返回False
?
NPE*_*NPE 82
这是特定于实现的,但您的解释器可能是实时编译时常量,但不是运行时表达式的结果.
接下来我使用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)
Run Code Online (Sandbox Code Playgroud)
第三个示例涉及运行时连接,其结果不会自动实现:
# 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
Run Code Online (Sandbox Code Playgroud)
如果您要手动intern()
执行第三个表达式的结果,您将获得与以前相同的对象:
>>> s3a = "strin"
>>> s3 = s3a + "g"
>>> s3 is "string"
False
>>> intern(s3) is "string"
True
Run Code Online (Sandbox Code Playgroud)
情况1
>>> x = "123"
>>> y = "123"
>>> x == y
True
>>> x is y
True
>>> id(x)
50986112
>>> id(y)
50986112
Run Code Online (Sandbox Code Playgroud)
案例2
>>> x = "12"
>>> y = "123"
>>> x = x + "3"
>>> x is y
False
>>> x == y
True
Run Code Online (Sandbox Code Playgroud)
现在,您的问题是为什么 id 在情况 1 中相同,而在情况 2 中不同。在情况 1 中,您已为和
分配了一个字符串文字。"123"
x
y
由于字符串是不可变的,因此解释器只存储一次字符串并将所有变量指向同一个对象是有意义的。
因此你会看到 id 是相同的。
在情况 2 中,您正在x
使用串联进行修改。x
和两者y
具有相同的值,但身份不同。
两者都指向内存中的不同对象。因此它们有不同的操作id
符is
返回False