Python 字符串驻留
- 2024-12-02 08:41:00
- admin 原创
- 138
问题描述:
虽然这个问题在实践中没有任何实际用途,但我很好奇 Python 如何进行字符串驻留。我注意到了以下内容。
>>> "string" is "string"
True
这正如我所料。
你也可以这样做。
>>> "strin"+"g" is "string"
True
这很聪明!
但你不能这么做。
>>> s1 = "strin"
>>> s2 = "string"
>>> s1+"g" is s2
False
为什么 Python 不计算s1+"g"
,并意识到它与 相同s2
,并将其指向相同的地址?在最后一个块中究竟发生了什么,让它返回False
?
解决方案 1:
这是特定于实现的,但是您的解释器可能正在实习编译时常量而不是运行时表达式的结果。
下文中使用 CPython 3.9.0+。
在第二个示例中,表达式"strin"+"g"
在编译时进行求值,并被替换为"string"
。这使得前两个示例的行为相同。
如果我们检查字节码,我们会发现它们完全相同:
# s1 = "string"
1 0 LOAD_CONST 0 ('string')
2 STORE_NAME 0 (s1)
# s2 = "strin" + "g"
2 4 LOAD_CONST 0 ('string')
6 STORE_NAME 1 (s2)
这个字节码是通过以下方式获得的(在上面之后打印几行):
import dis
source = 's1 = "string"
s2 = "strin" + "g"'
code = compile(source, '', 'exec')
print(dis.dis(code))
第三个示例涉及运行时连接,其结果不会自动保留:
# s3a = "strin"
3 8 LOAD_CONST 1 ('strin')
10 STORE_NAME 2 (s3a)
# s3 = s3a + "g"
4 12 LOAD_NAME 2 (s3a)
14 LOAD_CONST 2 ('g')
16 BINARY_ADD
18 STORE_NAME 3 (s3)
20 LOAD_CONST 3 (None)
22 RETURN_VALUE
该字节码是通过以下方式获得的(它在上面的内容之前打印了几行,这些行与上面给出的第一个字节码块完全相同):
import dis
source = (
's1 = "string"
'
's2 = "strin" + "g"
'
's3a = "strin"
'
's3 = s3a + "g"')
code = compile(source, '', 'exec')
print(dis.dis(code))
如果您手动获取sys.intern()
第三个表达式的结果,您将获得与之前相同的对象:
>>> import sys
>>> s3a = "strin"
>>> s3 = s3a + "g"
>>> s3 is "string"
False
>>> sys.intern(s3) is "string"
True
此外,Python 3.9 会对上面最后两个语句打印警告:
语法警告:“is”与文字有关。您的意思是“==”吗?
解决方案 2:
案例 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
andis
运算符False
相关推荐
热门文章
项目管理软件有哪些?
热门标签
云禅道AD