专栏名称: Python程序员
最专业的Python社区,有每日推送,免费电子书,真人辅导,资源下载,各类工具。我已委托“维权骑士”(rightknights.com)为我的文章进行维权行动
目录
相关文章推荐
Python爱好者社区  ·  “给我滚出贵大!”郑强出任贵州大学校长,打算 ... ·  3 天前  
Python爱好者社区  ·  DeepSeek 最新中国大学排名 ·  昨天  
Python开发者  ·  国产 DeepSeek V3 ... ·  5 天前  
Python爱好者社区  ·  史上最强!PINN杀疯了 ·  4 天前  
Python爱好者社区  ·  英伟达憾失DeepSeek关键人才?美国放走 ... ·  4 天前  
51好读  ›  专栏  ›  Python程序员

Python隐藏特性:字符串驻留、常量折叠

Python程序员  · 公众号  · Python  · 2019-12-24 08:10

正文

下面是Python字符串的一些微妙的特性,绝对会让你大吃一惊。


案例一:

>>> a = "some_string">>> id(a)140420665652016>>> id("some" + "_" + "string") # 注意两个的id值是相同的.140420665652016


案例二:

>>> a = "wtf">>> b = "wtf">>> a is bTrue
>>> a = "wtf!">>> b = "wtf!">>> a is bFalse
>>> a, b = "wtf!", "wtf!">>> a is bTrue # 3.7 版本返回结果为 False.


案例三:

>>> 'a' * 20 is 'aaaaaaaaaaaaaaaaaaaa'True>>> 'a' * 21 is 'aaaaaaaaaaaaaaaaaaaaa'False # 3.7 版本返回结果为 True


很好理解, 对吧?

💡 说明:

  • 这些行为是由于 Cpython 在编译优化时, 某些情况下会尝试使用已经存在的不可变对象而不是每次都创建一个新对象. (这种行为被称作字符串的驻留[string interning])

  • 发生驻留之后, 许多变量可能指向内存中的相同字符串对象. (从而节省内存)

  • 在上面的代码中, 字符串是隐式驻留的. 何时发生隐式驻留则取决于具体的实现. 这里有一些方法可以用来猜测字符串是否会被驻留:

    • 所有长度为 0 和长度为 1 的字符串都被驻留.

    • 字符串在编译时被实现 ( 'wtf' 将被驻留, 但是 ''.join(['w', 't', 'f']) 将不会被驻留)

    • 字符串中只包含字母,数字或下划线时将会驻留. 所以 'wtf!' 由于包含 ! 而未被驻留. 可以在【 地址1】 找到 CPython 对此规则的实现.

  • 当在同一行将 a b 的值设置为 "wtf!" 的时候, Python 解释器会创建一个新对象, 然后同时引用第二个变量(译: 仅适用于3.7以下, 详细情况请看【地址2】). 如果你在不同的行上进行赋值操作, 它就不会“知道”已经有一个 wtf! 对象 (因为 "wtf!" 不是按照上面提到的方式被隐式驻留的). 它是一种编译器优化, 特别适用于交互式环境.

  • 常量折叠(constant folding) 是 Python 中的一种 窥孔优化(peephole optimization) 技术. 这意味着在编译时表达式 'a'*20 会被替换为 'aaaaaaaaaaaaaaaaaaaa' 以减少运行时的时钟周期. 只有长度小于 20 的字符串才会发生常量折叠. (为啥? 想象一下由于表达式 'a'*10**10 而生成的 .pyc 文件的大小). 相关的源码实现







请到「今天看啥」查看全文