驚奇時刻!盤點哪些讓你大呼“真牛”的 Python 代碼!
Python 作為一個設(shè)計優(yōu)美的高級語言,提供了很多簡單易用的特性,但簡單并不意味著容易理解,有時候一些輸出結(jié)果對于剛?cè)腴T的小伙伴并不是很明了,反而似乎有點反人類。
今天派森醬就整理了一些非常有趣的例子,事實上這些例子不僅有趣,甚至還可以加深你對 Python 的理解,學(xué)到更多有趣的特性。
0x00
- >>> 'a' * 20 is 'aaaaaaaaaaaaaaaaaaaa'
- True
- >>> 'a' * 21 is 'aaaaaaaaaaaaaaaaaaaaa'
- False # 2.7 版本返回 False
- # 3.7 版本返回結(jié)果為 True
很神奇的一個結(jié)果,第一次看到時我也驚呆了,事實上這是 Python 的一種優(yōu)化機制,叫常量折疊。這意味著在編譯時表達(dá)式 'a'*20 會被替換為 aaaaaaaaaaaaaaaaaaaa 以減少運行時時常,而只有長度小于 20 的字符串才會發(fā)生常量折疊。
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
這是因為在編譯優(yōu)化時 Python 會嘗試使用一些已經(jīng)存在的不可辨對象,這種現(xiàn)象稱之為字符串駐留,而只包含字母數(shù)字和下劃線的字符串在編譯時是會駐留的,包含 ! 的字符串是不會駐留的。
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 字典通過比較不可變對象是否相等和哈希值是否相等來確定是否為不同的鍵,但不同值的對象也可能具有相同的哈希值。因此字典以為 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'
函數(shù)的返回值由最后 return 的語句決定,而 finally 一定是最后之行的,所以會覆蓋掉 try 中的 return 結(jié)果。
0x04
- In [23]: for i in range(3):
- ...: print(i)
- ...: i = 10
- ...:
- 0
- 1
- 2
在每次循環(huán)開始之前, 迭代器生成的下一個元素會重新賦值給 i,因此賦值語句 i = 10 并不會影響循環(huán)。
0x05
- In [24]: row = [''] * 3
- In [25]: table = [row] * 3
- In [26]: table
- Out[26]: [['', '', ''], ['', '', ''], ['', '', '']]
- In [27]: table[0][0] = 'python'
- In [28]: table
- Out[28]: [['python', '', ''], ['python', '', ''], ['python', '', '']]
這是因為通過乘法初始化 table 時,每個 item 也就是 table[0]、table[1]、table[2] 在內(nèi)存中引用的都是同一個列表。
0x06
- In [29]: a = 256
- In [30]: b = 256
- In [31]: a is b
- Out[31]: True
- In [32]: a = 257
- In [33]: b = 257
- In [34]: a is b
- Out[34]: False
產(chǎn)生這種現(xiàn)象的根本原因就是 256 是一個已經(jīng)存在的對象而 257 不是,事實上當(dāng) Python 啟動時數(shù)值為 -5 到 256 這些常用的的對象就已經(jīng)被分配好了。
0x07
- In [37]: 'something' is not None
- Out[37]: True
- In [38]: 'something' is (not None)
- Out[38]: False
這是因為 is not 是一個單獨的二元運算符,如果運算符兩側(cè)的變量指向同一個對象, 則 is not 的結(jié)果為 False, 否則為 True。
0x08
- In [47]: a = [1, 2, 3, 4]
- In [48]: b = a
- In [49]: a = a + [5, 6, 7, 8]
- In [50]: a
- Out[50]: [1, 2, 3, 4, 5, 6, 7, 8]
- In [51]: b
- Out[51]: [1, 2, 3, 4]
- In [52]: a = [1, 2, 3, 4]
- In [53]: b = a
- In [54]: a += [5, 6, 7, 8]
- In [55]: a
- Out[55]: [1, 2, 3, 4, 5, 6, 7, 8]
- In [56]: b
- Out[56]: [1, 2, 3, 4, 5, 6, 7, 8]
在第一個例子中 a = a + ... 會生成一個新的列表然后 a 指向這個列表,但 b 是保持不變的。
而第二個例子中的 a += ... 實際上是使用的是 extend 函數(shù),所以 a 和 b 指向的都是同一個列表。
0x09
- t = ('one', 'two')
- for i in t:
- print(i)
- print('*'*5)
- t = ('one')
- for i in t:
- print(i)
- print('*'*5)
- t = ()
- print(t)
- ## 輸出
- one
- two
- o
- n
- e
- tuple()
在 Python 的世界 () 是一個特殊的標(biāo)記,表示空元組,這個非常容易理解。
而 t = ('one') 或者 t = 'one' 都是會被解釋成為字符串的。正確的寫法應(yīng)該是 t = ('one',)。
總結(jié)
今天派森醬帶領(lǐng)大家整理了一些 Python 中比較好玩有趣的代碼,覺得眼前一亮的同時還可以順帶更深刻的理解 Python 的設(shè)計思想,一舉兩得。