查看原文
其他

What the f*ck Python!

老逛 逛逛GitHub 2021-08-19
这个 GitHub 相当有趣,作者收集了一些奇怪的 Python 代码片段,当你敲完这些代码片段,运行看到结果,会惊呼:What the f*ck!因为这些代码的输出结果会和你想象中的不太一样。
具体是什么原因你可能也说不明白,我们可以通过探寻产生这种结果的原因,对 Python 的内部原理理解的更加透彻。我举几个例子看看:
1. 魔幻的字符串
>>> a = "some_string"
>>> id(a)
140420665652016
>>> id("some" + "_" + "string") # 注意两个的id值是相同的.
140420665652016
2. 等号的错觉
>>> a = "wtf"
>>> b = "wtf"
>>> a is b
True

>>> a = "wtf!"
>>> b = "wtf!"
>>> a is b
False

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

当在同一行将 a 和 b 的值设置为 "wtf!" 的时候, Python 解释器会创建一个新对象,同时引用第二个变量。

如果你在不同的行上进行赋值操作, 它就不会 “知道” 已经有一个 wtf! 对象 (因为 "wtf!" 包含叹号,是无法被隐式驻留),它是一种编译器优化, 特别适用于交互式环境。

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

发生驻留之后, 许多变量可能指向内存中的相同字符串对象,从而达到节省内存的目的。

何时发生隐式驻留则取决于具体的实现。这里有一些方法可以用来猜测字符串是否会被驻留:
  • 所有长度为 0 和长度为 1 的字符串都被驻留.
  • 字符串在编译时被实现,'wtf' 将被驻留, 但是 ''.join(['w', 't', 'f']) 将不会被驻留
  • 字符串中只包含字母,数字或下划线时将会驻留。所以 'wtf!' 由于包含 ! 而未被驻留。可以在这里找到 CPython 对此规则的实现。
3. 这是为啥?
>>> 'a' * 20 is 'aaaaaaaaaaaaaaaaaaaa'
True
>>> 'a' * 21 is 'aaaaaaaaaaaaaaaaaaaaa'
False # 3.7 版本返回结果为 True

对于 'a' * 21 为啥返回 False,这其实涉及到常量折叠的技术,这种技术是 Python 中的一种窥孔优化技术,在编译时表达式 'a'*20 会被替换为 'aaaaaaaaaaaaaaaaaaaa' 以减少运行时的时钟周期,只有长度小于 20 的字符串才会发生常量折叠。

还有很多这样的代码片段,欢迎关注微信公众号「逛逛GitHub」回复「wtf」获取这个开源项目地址。

这个项目有万人 Star,相信 What the f*ck Java 开源项目也不远了,感兴趣的小伙伴可以整一个,整完把地址给我,我帮你推荐一下。

最后,防止找不到本篇文章,可以收藏点赞,方便翻阅查找。本文首发至公众号 逛逛GitHub(ggGithub),转载请注明出处。


推荐阅读
1. 推荐几个好玩项目
2. 推荐几个有用项目
3. 推荐几个有用工具

每天推荐一个有趣、好玩且可能你会用到的 GitHub 项目。

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存