惊奇时刻!盘点哪些让你大呼“卧槽”的 Python 代码!(上)

0x00

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

惊奇时刻!盘点哪些让你大呼“卧槽”的 Python 代码!(上)

很神奇的一个结果,第一次看到时我也惊呆了,事实上这是 Python 的一种优化机制,叫常量折叠。这意味着在编译时表达式 'a'*20 会被替换为 aaaaaaaaaaaaaaaaaaaa 以减少运行时时常,而只有长度小于 20 的字符串才会发生常量折叠。

0x01

In [3]: a = 'python'
In [4]: b = 'python'
In [5]: a is b
Out[5]: True
In [6]: x = 'python!'
In [7]: y = 'python!'
In [8]: x is y
Out[8]: False


惊奇时刻!盘点哪些让你大呼“卧槽”的 Python 代码!(上)这是因为在编译优化时 Python 会尝试使用一些已经存在的不可辨对象,这种现象称之为字符串驻留,而只包含字母数字和下划线的字符串在编译时是会驻留的,包含 ! 的字符串是不会驻留的。

0x02

In [11]: some_dict = {}
In [12]: some_dict[5.5] = 'Java'
In [13]: some_dict[5.0] = 'Ruby'
In [14]: some_dict[5] = 'Python'
In [15]: some_dict[5.5] + '_' + some_dict[5.0] + '_' + some_dict[5]
Out[15]: 'Java_Python_Python'
In [16]: 5 == 5.0
Out[16]: True
In [17]: hash(5) == hash(5.0)
Out[17]: True


惊奇时刻!盘点哪些让你大呼“卧槽”的 Python 代码!(上)

Python 字典通过比较不可变对象是否相等和哈希值是否相等来确定是否为不同的键,但不同值的对象也可能具有相同的哈希值。因此字典以为 5.0 和 5 是同一个键,所以 Python 会覆盖掉 Ruby。

0x03

In [21]: def some_func():
    ...:     try:
    ...:         return 'from_try'
    ...:     finally:
    ...:         return 'from_finally'
    ...:
In [22]: some_func()
Out[22]: 'from_finally'

惊奇时刻!盘点哪些让你大呼“卧槽”的 Python 代码!(上)函数的返回值由最后 return 的语句决定,而 finally 一定是最后之行的,所以会覆盖掉 try 中的 return 结果。

0x04

In [23]: for i in range(3):
    ...:     print(i)
    ...:     i = 10
    ...:
0
1
2

惊奇时刻!盘点哪些让你大呼“卧槽”的 Python 代码!(上)

在每次循环开始之前, 迭代器生成的下一个元素会重新赋值给 i,因此赋值语句 i = 10 并不会影响循环。

上一篇:Python异常还能写得如此优雅!


下一篇:linux安装python