首頁>技術>

英文:Satwik Kansal,翻譯:暮晨

Python開發者 整理自 GitHub

【導讀】:Python 是一個設計優美的解釋型高階語言,它提供了很多能讓程式設計師感到舒適的功能特性。但有的時候 Python 的一些輸出結果對於初學者來說似乎並不是那麼一目瞭然。

雖然有些例子並不一定會讓你覺得“臥槽”(WTF),但它們依然有可能會告訴你一些你所不知道的 Python 有趣特性。我覺得這是一種學習程式語言內部原理的好辦法,而且我相信你也會從中獲得樂趣!

如果你是一位經驗比較豐富的 Python 程式設計師,你可以嘗試挑戰看是否能一次就找到例子的正確答案。你可能對其中的一些例子已經比較熟悉了,那這也許能喚起你當年踩這些坑時的甜蜜回憶。

今天我們的主角是字串,讓我們開始吧!

微妙的字串

1.

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

2.

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

3.

>>> '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)[3] 技術. 這意味著在編譯時表示式 'a'*20 會被替換為 'aaaaaaaaaaaaaaaaaaaa' 以減少執行時的時鐘週期. 只有長度小於 20 的字串才會發生常量摺疊. (為啥? 想象一下由於表示式 'a'*10**10 而生成的 .pyc 檔案的大小). 相關的原始碼實現在這裡[4].如果你是使用 3.7 版本中執行上述示例程式碼, 會發現部分程式碼的執行結果與註釋說明相同. 這是因為在 3.7 版本中, 常量摺疊已經從窺孔最佳化器遷移至新的 AST 最佳化器, 後者可以以更高的一致性來執行最佳化. (由 Eugene Toder 和 INADA Naoki 在 bpo-29469[5]bpo-11549[6] 中貢獻.)(但是在最新的 3.8 版本中, 結果又變回去了. 雖然 3.8 版本和 3.7 版本一樣, 都是使用 AST 最佳化器. 目前不確定官方對 3.8 版本的 AST 做了什麼調整.)參考資料

[1]

https://github.com/python/cpython/blob/3.6/Objects/codeobject.c#L19

[2]

https://github.com/leisurelicht/wtfpython-cn/issues/13

[3]

窺孔最佳化(peephole optimization): https://en.wikipedia.org/wiki/Peephole_optimization

[4]

https://github.com/python/cpython/blob/3.6/Python/peephole.c#L288

[5]

bpo-29469: https://bugs.python.org/issue29469

[6]

bpo-11549: https://bugs.python.org/issue11549

14
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • C語言 | 輸入一個數,輸出相應result