如果Python字符串是不可变的,为什么如果我使用+=追加到它,它会保持相同的id?
2022/7/6 14:23:28
本文主要是介绍如果Python字符串是不可变的,为什么如果我使用+=追加到它,它会保持相同的id?,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
Python中的字符串是不可变的,这意味着该值无法更改。但是,在以下示例中追加到字符串时,由于 id 保持不变,因此原始字符串内存似乎已被修改:
>>> s = 'String' >>> for i in range(5, 0, -1): ... s += str(i) ... print(f"{s:<11} stored at {id(s)}") ... String5 stored at 139841228476848 String54 stored at 139841228476848 String543 stored at 139841228476848 String5432 stored at 139841228476848 String54321 stored at 139841228476848
相反,在以下示例中,id 会更改:
>>> a = "hello" >>> id(a) 139841228475760 >>> a = "b" + a[1:] >>> print(a) bello >>> id(a) 139841228475312118
这是一个特定于CPython的优化,适用于被追加到碰巧没有其他活引用的情况。在这种情况下,解释器“作弊”,允许它通过重新分配(可以就位,具体取决于堆布局)和直接附加数据来修改现有字符串,并且经常在重复连接的循环中显着减少工作(使其行为更像a的摊销追加而不是每次复制操作)。除了未更改的之外,它没有可见的效果,因此这样做是合法的(除非在逻辑上被替换,否则具有现有引用的人都不会看到它发生变化)。str
O(1)
list
O(n)
id
str
str
你实际上不应该依赖它(非引用计数的解释器不能使用这个技巧,因为他们不知道是否有其他引用),根据PEP8的第一个编程建议:str
代码的编写方式不应使Python的其他实现(PyPy,Jython,IronPython,Cython,Psyco等)不利。
例如,不要依赖 CPython 为 form 或 中的语句有效实现就地字符串串联。即使在CPython中,这种优化也很脆弱(它仅适用于某些类型),并且在不使用refcounting的实现中根本不存在。在库的性能敏感部分,应改用表单。这将确保在各种实现中以线性时间进行串联。
a += b
a = a + b
''.join()
如果你想打破优化,有各种各样的方法可以做到这一点,例如,将你的代码更改为:
>>> while i!=0: ... s_alias = s # Gonna save off an alias here ... s += str(i) ... print(s + " stored at " + str(id(s))) ... i -= 1 ...
通过创建别名,增加引用计数并告诉Python更改将在 其他位置可见来破坏它,因此它无法应用它。类似地,像这样的代码:s
s = s + a + b
不能使用它,因为首先发生,并产生一个临时的,然后必须添加到,而不是立即替换,并且优化太脆而无法尝试处理。几乎相同的代码,如:s + a
b
s
s += a + b
艺术
s = s + (a + b)
通过确保最终串联始终是左操作数的位置,并且结果用于立即替换 来恢复优化。
这篇关于如果Python字符串是不可变的,为什么如果我使用+=追加到它,它会保持相同的id?的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-26Python基础编程
- 2024-11-25Python编程基础:变量与类型
- 2024-11-25Python编程基础与实践
- 2024-11-24Python编程基础详解
- 2024-11-21Python编程基础教程
- 2024-11-20Python编程基础与实践
- 2024-11-20Python编程基础与高级应用
- 2024-11-19Python 基础编程教程
- 2024-11-19Python基础入门教程
- 2024-11-17在FastAPI项目中添加一个生产级别的数据库——本地环境搭建指南