【小思考】Python裡面有聲明和定義分離這一說嗎?

來源:互聯網
上載者:User

標籤:效果   分享圖片   處理   自己   答案   方法   ros   問題:   size   

第一部分:

探究這個問題,還是因為編程的時候碰到了這個錯誤:

提示tcplink沒有定義,tcplink是我自己寫的一個給監聽到的tcp串連請求分配新線程的函數,不過是寫在了下面,就像這樣:

如果是C++裡面的話,解決這個問題很簡單。在檔案開頭的時候,加上該函數的聲明式就OK,這樣不僅方便,還能最大限度的保持美觀(霧)。但是問題來了,Python裡面好像沒有聲明和定義這一說呀!

到底有沒有呢?這個得要從Python指令碼的運行機制來看了。

在C++裡面,聲明是告訴編譯器我的程式裡將會有這個符號,編譯器將聲明內容進行記錄,在定義處記錄入口,分配記憶體。換言之,由於C++是編譯型語言,這就可以對完整的程式進行掃描,進行跨文本域的聯絡。

然而,Python卻不可以,Python是解釋型語言,雖然我們自己寫的指令碼是一個完整檔案,但是在給Python解譯器執行的時候,依然相當於是把指令檔裡的內容一行一行輸入進解譯器並執行。這就造成了如果執行的當前語句要調用tcplink,解譯器立馬會在之前輸入的內容中尋找tcplink的定義並執行,如果無法執行則報錯。因為有這個機制,直接就導致了不能像C/C++那樣,先放個聲明式在前面,在把定義放到其他地方。

第二部分:

有些人可能會問,拉倒吧,我編程的時候這樣寫,funcb在funcc前面,funcb內將執行funcc,為啥啟動並執行時候什麼錯誤都不會報呢?

這就更有的說了,我們先來把這一小段放到Python命令列互動模式下,看結果如何:

對,依然也是什麼錯誤都沒發生。那麼,根據之前所說,Python解譯器是進來一行解釋一行,如果無法解釋就會立馬報錯,為什麼這裡解譯器讀入了funcc,使用者也沒有進行funcc的定義,解譯器卻沒有報錯呢?

其實,“Python解譯器是進來一行解釋一行” 這種說法其實還不太嚴謹。細心的讀者能夠發現,當在Python解譯器輸入def funcb():並斷行符號的時候,>>>變成了...,只有在funcb使用者定義完成後並確認,才又會回到>>>。一般情況下,使用者是輸入一行斷行符號,>>>不發生改變,並輸出應該有的結果。所以這說明了什麼呢?兩點問題:

1.在定義funcb()的時候,使用者的斷行符號沒有讓輸入的語句執行。

2.定義完成funcb()向解譯器發送斷行符號確認的時候,解譯器也沒有執行之前定義內的內容。(因為如果執行了,一定會報錯,就像下面這樣)

新的問題又出現了,所以之前解譯器到底執行了什嗎?答案就是:執行了“定義funcb()”這一個語句。這樣,第二部分開頭的那個問題,我想大家心裡應該有答案了。把第二部分開頭的那段程式執行過程畫個圖來理解,就像這樣:

簡而言之,如果當前只是執行了“定義XXX”的語句,解譯器並不關心你具體定義的內容,此時進來的內容,解譯器暫不執行。所以由於之前的funcc()是funcb()內定義的內容,自然不執行,也就無關乎是否此時存在funcc()。但!如果我此時調用funcb,解譯器就會轉而執行funcb內的具體內容,此時如果funcc()還沒有被定義,一定會報not defined的錯誤!咱們來驗證一下:

看來,說的不錯。而第二部分開頭的代碼,在funcc實際被執行的時候,已經獲得了完整的定義,故就不會報not defined的錯誤拉~

第三部分:

那麼,有沒有什麼方法,能夠讓我的Python程式看起來更加整潔美觀——不讓所謂的“主程式”檔案內函數太多而顯得雜亂呢?

其實,import是個挺不錯的方法,稍微熟悉Python的人都明白,import可以引用其他地方的py等模組,還可以用from module import function的形式,單獨引入指定模組內的指定函數、類。

甚至!!

對於一個從C++過來的人,真是傻了。Python的import相當於“把import的東西原封不動塞進import處一整坨”,所以由於是在函數定義內import的,所以import的東西只有在該函數內才可使用~然而C++/C的單獨#include預先處理指令則是做不到的。

等等。是不是錯過了什麼重要的東西……

是的,如果import直接匯入本檔案,是否是可以的呢?如果可以的話,那豈不是之前的例子中,在之前加上:

from 本檔案 import funca/b/c,就可以實作類別似C++函式宣告的作用了?萬一成功了,那豈不是……真香?

我們來試試:

看來,真香失敗。那麼,為什麼這種方法不行呢?我們來回顧一下第二部分中部那個我自己畫的流程圖,由於Python解譯器是進來一句執行一句,所以這裡執行的內容是:匯入daliywork中的funcb。執行這一句的時候,funcb沒有定義,故匯入失敗。

第四部分:

最後一個問題,如果import整個檔案自己本身,可不可以實現這種結果呢?(就和只執行定義XXX時解譯器不會探究具體定義的內容一樣,這種只執行匯入整個檔案的操作,解譯器是否會關心整個檔案內的具體內容呢?)

我們再來回顧一下第三部分內關於import一個很直觀的解釋:

好了,有了這個解釋,我覺得大部分人心裡已經有答案了。測試代碼如下,我們直接執行來看一下結果:

異常棧首先提示funca沒有定義,指向daliywork第六行,但這個錯誤又是因為daliywork的第三行import導致的。這是因為import整個檔案後,相當於把除了import這句以外的部分,替換到了import本身的地方,然後執行這些代碼,這時候,在引入的部分內,執行到funca,發現還是沒有進行定義,這時候再報出funca沒有進行定義的錯誤。需要注意,錯誤內報了funca沒有經過定義,並不是報的執行檔案中的funca沒有定義(因為此時在源檔案line3 import這一句就已經拋出異常了,程式已經停在這裡了!),而是import的daliywork裡面的第六行出現的錯誤。這一點十分重要,可以用以下的圖解進行解釋(PS:畫圖真好用):

雖然引入的內容裡,包括了所有的定義內容,但是由於引入的檔案也會發生執行,所以依然無法實現我們想要的效果……

看來,由於Python特殊的解釋執行機制,導致了沒什麼方法可以只把函數的聲明提前。以後寫代碼的時候,還是乖乖要麼把定義的函數都放到其他檔案通過import module方式匯入,通過module.function()形式進行調用;要麼乖乖放在要執行該函數的代碼的前面吧……

 

 

 

無題

 聲明定義要分離,Python解釋行不行?

千變萬化難類比,繞了一圈空歎息。

 

 

 

【小思考】Python裡面有聲明和定義分離這一說嗎?

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.