<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          一些有趣且鮮為人知的 Python 特性

          共 5395字,需瀏覽 11分鐘

           ·

          2021-05-23 12:38

          一些有趣且鮮為人知的 Python 特性
          GENERAL TITLE
          Structure of the Examples/示例結(jié)構(gòu)

          Output (Python version):

          >>> 觸發(fā)語(yǔ)句
          出乎意料的輸出結(jié)果

          (可選): 對(duì)意外輸出結(jié)果的簡(jiǎn)短描述.

          ?? 說(shuō)明:

          • 簡(jiǎn)要說(shuō)明發(fā)生了什么以及為什么會(huì)發(fā)生.

            如有必要, 舉例說(shuō)明

            Output:

            >>> 觸發(fā)語(yǔ)句 # 一些讓魔法變得容易理解的例子# 一些正常的輸入

          注意: 所有的示例都在 Python 3.5.2 版本的交互解釋器上測(cè)試過(guò), 如果不特別說(shuō)明應(yīng)該適用于所有 Python 版本.

          Usage/用法

          我個(gè)人建議, 最好依次閱讀下面的示例, 并對(duì)每個(gè)示例:

          • 仔細(xì)閱讀設(shè)置例子最開(kāi)始的代碼. 如果您是一位經(jīng)驗(yàn)豐富的 Python 程序員, 那么大多數(shù)時(shí)候您都能成功預(yù)期到后面的結(jié)果.

          • 閱讀輸出結(jié)果,

            • 如果不知道, 深呼吸然后閱讀說(shuō)明 (如果你還是看不明白, 別沉默! 可以在這提個(gè) issue).

            • 如果知道, 給自己點(diǎn)獎(jiǎng)勵(lì), 然后去看下一個(gè)例子.

            • 確認(rèn)結(jié)果是否如你所料.

            • 確認(rèn)你是否知道這背后的原理.

          PS: 你也可以在命令行閱讀 WTFpython. 我們有 pypi 包 和 npm 包(支持代碼高亮).(譯: 這兩個(gè)都是英文版的)

          安裝 npm 包 wtfpython

          $ npm install -g wtfpython

          或者, 安裝 pypi 包 wtfpython

          $ pip install wtfpython -U

          現(xiàn)在, 在命令行中運(yùn)行 wtfpython, 你就可以開(kāi)始瀏覽了.

          ?? Examples/示例

          Section: Strain your brain!/大腦運(yùn)動(dòng)!

          > Strings can be tricky sometimes/微妙的字符串 *

          1.

          >>> a = "some_string"
          >>> id(a)
          140420665652016
          >>> id("some" + "_" + "string")# 注意兩個(gè)的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 版本返回結(jié)果為 False.

          3.

          >>> 'a' * 20 is 'aaaaaaaaaaaaaaaaaaaa'
          True
          >>> 'a' * 21 is 'aaaaaaaaaaaaaaaaaaaaa'
          False # 3.7 版本返回結(jié)果為 True

          很好理解, 對(duì)吧?

          ?? 說(shuō)明:

          • 這些行為是由于 Cpython 在編譯優(yōu)化時(shí), 某些情況下會(huì)嘗試使用已經(jīng)存在的不可變對(duì)象而不是每次都創(chuàng)建一個(gè)新對(duì)象. (這種行為被稱(chēng)作字符串的駐留[string interning])

          • 發(fā)生駐留之后, 許多變量可能指向內(nèi)存中的相同字符串對(duì)象. (從而節(jié)省內(nèi)存)

          • 在上面的代碼中, 字符串是隱式駐留的. 何時(shí)發(fā)生隱式駐留則取決于具體的實(shí)現(xiàn). 這里有一些方法可以用來(lái)猜測(cè)字符串是否會(huì)被駐留:

            • 所有長(zhǎng)度為 0 和長(zhǎng)度為 1 的字符串都被駐留.

            • 字符串在編譯時(shí)被實(shí)現(xiàn) ('wtf' 將被駐留, 但是 ''.join(['w', 't', 'f']) 將不會(huì)被駐留)

            • 字符串中只包含字母,數(shù)字或下劃線(xiàn)時(shí)將會(huì)駐留. 所以 'wtf!' 由于包含 ! 而未被駐留. 可以在這里找到 CPython 對(duì)此規(guī)則的實(shí)現(xiàn).



          • 當(dāng)在同一行將 a 和 b 的值設(shè)置為 "wtf!" 的時(shí)候, Python 解釋器會(huì)創(chuàng)建一個(gè)新對(duì)象, 然后同時(shí)引用第二個(gè)變量(譯: 僅適用于3.7以下, 詳細(xì)情況請(qǐng)看這里). 如果你在不同的行上進(jìn)行賦值操作, 它就不會(huì)“知道”已經(jīng)有一個(gè) wtf! 對(duì)象 (因?yàn)?nbsp;"wtf!" 不是按照上面提到的方式被隱式駐留的). 它是一種編譯器優(yōu)化, 特別適用于交互式環(huán)境.

          • 常量折疊(constant folding) 是 Python 中的一種 窺孔優(yōu)化(peephole optimization) 技術(shù). 這意味著在編譯時(shí)表達(dá)式 'a'*20 會(huì)被替換為 'aaaaaaaaaaaaaaaaaaaa' 以減少運(yùn)行時(shí)的時(shí)鐘周期. 只有長(zhǎng)度小于 20 的字符串才會(huì)發(fā)生常量折疊. (為啥? 想象一下由于表達(dá)式 'a'*10**10 而生成的 .pyc 文件的大小). 相關(guān)的源碼實(shí)現(xiàn)在這里.

          • 如果你是使用 3.7 版本中運(yùn)行上述示例代碼, 會(huì)發(fā)現(xiàn)部分代碼的運(yùn)行結(jié)果與注釋說(shuō)明相同. 這是因?yàn)樵?3.7 版本中, 常量折疊已經(jīng)從窺孔優(yōu)化器遷移至新的 AST 優(yōu)化器, 后者可以以更高的一致性來(lái)執(zhí)行優(yōu)化. (由 Eugene Toder 和 INADA Naoki 在 bpo-29469 和 bpo-11549 中貢獻(xiàn).)

          • (譯: 但是在最新的 3.8 版本中, 結(jié)果又變回去了. 雖然 3.8 版本和 3.7 版本一樣, 都是使用 AST 優(yōu)化器. 目前不確定官方對(duì) 3.8 版本的 AST 做了什么調(diào)整.)

          > Time for some hash brownies!/是時(shí)候來(lái)點(diǎn)蛋糕了!

          • hash brownie指一種含有大麻成分的蛋糕, 所以這里是句雙關(guān)

          1.

          some_dict = {}
          some_dict[5.5] = "Ruby"
          some_dict[5.0] = "JavaScript"
          some_dict[5] = "Python"

          Output:

          >>> some_dict[5.5]
          "Ruby"
          >>> some_dict[5.0]
          "Python"
          >>> some_dict[5]
          "Python"

          "Python" 消除了 "JavaScript" 的存在?

          ?? 說(shuō)明:

          • Python 字典通過(guò)檢查鍵值是否相等和比較哈希值來(lái)確定兩個(gè)鍵是否相同.

          • 具有相同值的不可變對(duì)象在Python中始終具有相同的哈希值.

          >>> 5 == 5.0
          True
          >>> hash(5) == hash(5.0)
          True


          注意: 具有不同值的對(duì)象也可能具有相同的哈希值(哈希沖突).

          • 當(dāng)執(zhí)行 some_dict[5] = "Python" 語(yǔ)句時(shí), 因?yàn)镻ython將 5 和 5.0 識(shí)別為 some_dict 的同一個(gè)鍵, 所以已有值 "JavaScript" 就被 "Python" 覆蓋了.

          • 這個(gè) StackOverflow的 回答 漂亮地解釋了這背后的基本原理.


          > Return return everywhere!/到處返回!

          def some_func():
          try:
          return 'from_try'
             finally:
          return 'from_finally'

          Output:

          >>> some_func()
          'from_finally'

          ?? 說(shuō)明:

          • 當(dāng)在 "try...finally" 語(yǔ)句的 try 中執(zhí)行 returnbreak 或 continue 后, finally 子句依然會(huì)執(zhí)行.

          • 函數(shù)的返回值由最后執(zhí)行的 return 語(yǔ)句決定. 由于 finally 子句一定會(huì)執(zhí)行, 所以 finally 子句中的 return 將始終是最后執(zhí)行的語(yǔ)句.


          > Deep down, we're all the same./本質(zhì)上,我們都一樣. *

          class WTF:
          pass

          Output:

          >>> WTF() == WTF() # 兩個(gè)不同的對(duì)象應(yīng)該不相等
          False
          >>> WTF() is WTF() # 也不相同
          False
          >>> hash(WTF()) == hash(WTF()) # 哈希值也應(yīng)該不同
          True
          >>> id(WTF()) == id(WTF())
          True

          ?? 說(shuō)明:

          • 當(dāng)調(diào)用 id 函數(shù)時(shí), Python 創(chuàng)建了一個(gè) WTF 類(lèi)的對(duì)象并傳給 id 函數(shù). 然后 id 函數(shù)獲取其id值 (也就是內(nèi)存地址), 然后丟棄該對(duì)象. 該對(duì)象就被銷(xiāo)毀了.

          • 當(dāng)我們連續(xù)兩次進(jìn)行這個(gè)操作時(shí), Python會(huì)將相同的內(nèi)存地址分配給第二個(gè)對(duì)象. 因?yàn)?(在CPython中) id 函數(shù)使用對(duì)象的內(nèi)存地址作為對(duì)象的id值, 所以?xún)蓚€(gè)對(duì)象的id值是相同的.

          • 綜上, 對(duì)象的id值僅僅在對(duì)象的生命周期內(nèi)唯一. 在對(duì)象被銷(xiāo)毀之后, 或被創(chuàng)建之前, 其他對(duì)象可以具有相同的id值.

          • 那為什么 is 操作的結(jié)果為 False 呢? 讓我們看看這段代碼.

          class WTF(object):
          def __init__(self): print("I")
          def __del__(self): print("D")

          Output:

          >>> WTF() is WTF()
          I
          I
          D
          D
          False
          >>> id(WTF()) == id(WTF())
          I
          D
          I
          D
          True

          正如你所看到的, 對(duì)象銷(xiāo)毀的順序是造成所有不同之處的原因.


          > For what?/為什么?

          some_string = "wtf"
          some_dict = {}
          for i, some_dict[i] in enumerate(some_string):
          pass

          Output:

          >>> some_dict # 創(chuàng)建了索引字典.
          {0: 'w', 1: 't', 2: 'f'}

          ?? 說(shuō)明:

          • Python 語(yǔ)法 中對(duì) for 的定義是:

          for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite

          其中 exprlist 指分配目標(biāo). 這意味著對(duì)可迭代對(duì)象中的每一項(xiàng)都會(huì)執(zhí)行類(lèi)似 {exprlist} = {next_value} 的操作.

          一個(gè)有趣的例子說(shuō)明了這一點(diǎn):

          for i in range(4):    print(i)    i = 10

          Output:

          0
          1
          2
          3

          你可曾覺(jué)得這個(gè)循環(huán)只會(huì)運(yùn)行一次?

          ?? 說(shuō)明:

            • 由于循環(huán)在Python中工作方式, 賦值語(yǔ)句 i = 10 并不會(huì)影響迭代循環(huán), 在每次迭代開(kāi)始之前, 迭代器(這里指 range(4)) 生成的下一個(gè)元素就被解包并賦值給目標(biāo)列表的變量(這里指 i)了.

          • 在每一次的迭代中, enumerate(some_string) 函數(shù)就生成一個(gè)新值 i (計(jì)數(shù)器增加) 并從 some_string 中獲取一個(gè)字符. 然后將字典 some_dict 鍵 i (剛剛分配的) 的值設(shè)為該字符. 本例中循環(huán)的展開(kāi)可以簡(jiǎn)化為:

          >>> i, some_dict[i] = (0, 'w')
          >>> i, some_dict[i] = (1, 't')
          >>> i, some_dict[i] = (2, 'f')
          >>> some_dict
          掃碼關(guān)注我們
          你會(huì)發(fā)現(xiàn),學(xué)無(wú)止境
          是一件值得驕傲的事情



          瀏覽 46
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  豆花视频免费 | 亚洲视频免费完整版在线播放 | 国产黄色视频网站免费 | 人人做天天摸夜夜添成人 | 久久免费的精品国产v∧ |