前兩天做了網易的一道選擇題:
問題描述:
python是用C語言寫成的,根據名字空間特性,以下程式碼經過python編譯器編譯後,一共得到()個PyCodeObject物件。
class A:
pass
def Fun():
pass
a = A()
Fun()
複製程式碼
....啥是PyCodeObject???
說來話不是很長
這裡分享一些學習的details。比如我在找尋A問題的原因,但是這時候B.C.D三個問題,越看越亂,最後:放棄。嘗試著徹底一些解決問題,就會慢慢上道。
Okay BB了這麼多,我想說的就是做事情要徹底,因為徹底之後會帶來美妙的空虛,不是黃段子,是崔健的歌(藍色骨頭)...
從頭開始 解釋性語言?編譯型語言?
編譯型語言和解釋型語言: 舉個例子你創作了一本書,這時候你想找翻譯幫你翻譯成英鍋歷史方便你成為網紅。那麼你的祕書找來了兩個翻譯,翻譯且列印:
1.編譯型翻譯(語言):從頭開始一直給你翻譯到你作品的最終一個標點符號,然後開始列印,1就可以歇了
2.解釋型翻譯(語言):就好像你媽在床頭給你講故事一樣,翻譯一句一句或者一段一段的,一句一句,然後一句一句一段一段列印,2一直陪著你
分析兩種方法優劣:
1執行效率高,一次成型電梯洋房拎包入住,按你胃,就是一旦翻譯完事,執行效率就很高了。
比如你讓1給你翻譯的時候,你發現呀我有一個字寫錯了,但是如果是1完成的話必須等他翻譯完,然後再改好再讓他翻譯一遍。那如果是2翻譯呢,一段一段一行一行,只需要重新翻譯那一行就好了啊?
小總結:
要把你的code轉化為電腦能看懂的語言,那麼有兩種計劃
1.編譯,像C一樣,一旦編譯成機器語言,直接給機器執行就好了,所以說執行效率很高很高
2.解釋,省去了編譯的過程,一行一行解釋直接執行,像ruby這樣的
WTF,說這麼久都沒說Python,那麼python是什麼?
Python與Java(基於虛擬機器的語言)一樣都是先編譯再解釋的語言,為什麼說它編譯過,很簡單你開啟尼德pycharm隨便寫一個.py檔案執行成功就會發現資料夾中多出來一個.pyc檔案,c就代表著complie啊,並且使用terminal執行.py檔案,你得輸入python xxx.py,對啊,這個詞就是在喚醒直譯器睡你MB起來嗨啊,給爸爸翻譯別睡了呆子~
關於語言的區別先說到這裡,接下來琢磨琢磨Python
pyc與PyCodeObject
先做一個小測試,我在本機寫了如下程式碼,執行成功後,我想看看我該檔案下是否有pyc檔案
我擦?WTF為什麼沒有呢?
接著我們在新建一個.py檔案把之前的memo檔案中的say方法import一下
啊? 為什麼pyc檔案又出來了?
原因: PyCodeObject實際上是,python編譯器在記憶體中編譯成的結果,pyc檔案可以看成是PyCodeObject在磁碟上的持久化,沒有出pyc檔案的原因是因為python直譯器認為重用的程式碼塊才值得搞pyc執行前在記憶體中看看是否在PyCodeObject中,如果在就不需要讀取磁碟本地的pyc檔案了。 過程如下
那麼回到最初的問題,貌似圈子繞的有點大了
解答這個問題前,先說明一個概念--Code Block:
Python編譯器在對Python原始碼進行編譯的時候,對程式碼中的一個Code Block,會建立一個PyCodeObject物件與這段程式碼對應。
如何確定多少程式碼算一個Code Block?
Python中確定Code Block的規則:當進入一個新的名字空間或作用域時,就算進入了一個新的Code Block了。
即:一個名字空間對應一個Code Block,它會對應一個PyCodeObject。
現在暫且認為名字空間就是符號的上下文環境,是名字到物件的對映。
在Python中,類、函式和module都對應著一個獨立的名字空間,因此都會對應一個PyCodeObject物件。
class A:
pass
def Fun():
pass
a = A()
Fun()
複製程式碼
Python編譯器對上面的code原始碼編譯之後,會建立3個PyCodeObject物件:第一個是對應整.py檔案代表的Code Block,第二個是對應Class A代表的Code Block,第三個是對應f代表的Code Block。
正確答案查了一下是三個,小手一抖 三分到手,That's all thx~