你已經使用 Python 編程了一段時間,編寫腳本並解決各種問題。是你的水平出色嗎?你可能只是在不知不覺中利用了Python的高級特性。
從閉包(closure)到上下文管理器(context managers),本文給出一個Python高級特性的列表。你或許會發現,「我一直在使用它!」。
即使這些東西對你來說是新的,這份出色的列表也可以將你的技術提升到一個新的水平。
一、作用域
高級 Python 編程的一個關鍵方面是深入熟悉作用域的概念。
作用域定義了 Python 解釋器在程序中查找名稱(它可以指代任何東西,變量、函數或類)定義的順序。Python 作用域遵循 LEGB 規則(本地、閉包、全局和內置作用域)。根據規則,當您訪問一個名稱時,解釋器將按順序在局部、封閉、全局和內置作用域中查找它。
讓我們看一些例子來更好地理解每個層級。
例1:本地作用域
此處只在func函數中局部定義了x,在腳本的其他位置無法訪問到x的定義。
例2:閉包作用域
閉包定義域介於局部定義和全局定義之間,是嵌套函數中出現的作用域。在上述例子中,x在outer_func函數本地定義,但嵌套其中的inner_func函數仍然可以訪問到x變量。但需要注意,inner_func對於x變量只有隻讀權限,即使重新為x賦值也只在inner_func內部產生作用,在outer_func函數中x的賦值並不會改變。(參考:https://qiwsir.github.io/2021/11/03/python-builtins-first/)
例3:全局作用域
此處,變量x和函數func都在全局定義,此二者可以在腳本的任何位置被訪問。但如果要在更小的作用域修改全局變量,需要用global關鍵字指定全局變量,示例如下。
例4:內置作用域
內置作用域包括所有不需要顯式導入語句的已定義的庫、類、函數和變量。例如Python中的內置函數:print, len, range等;以及內置變量:str, int, float等。
二、函數閉包
作用域的定義決定了函數的閉包特性。默認情況下,函數運行完後會並不會有返回值,這意味著函數占用的內存都會被抹去 。
上面,我們將值3賦給x,但函數在執行後忘記了它。如果我們不想讓它忘記x的值呢?
這就是函數閉包發揮作用的地方。通過在某個內部函數的封閉範圍內定義變量,即使在函數返回之後,也可以將其存儲在內部函數的內存中。
下面是一個簡單的示例函數,用於計算它被執行的次數。
根據Python規則,我們應該在第一次執行後失去count變量。但由於它在內部函數的閉包中定義,它將一直保留在那裡,直到關閉會話為止。
三、裝飾器
除了count變量,函數閉包還有更多重要作用,其中之一是創建裝飾器。裝飾器是一種嵌套函數,可以添加到其他函數以增強甚至修改它們的行為。
如下所示,我們創建了一個緩存裝飾器,它記住了函數的每個位置參數和關鍵字參數的狀態。
stateful_function裝飾器可以添加到需要在相同參數上重複使用的計算密集型函數中。例如,下面的斐波那契遞歸函數會返回序列中的第n個數字,如果我們調用剛才的裝飾器,代碼和結果如下:
第1000位數字僅耗時不到2秒!
如果我們不使用裝飾器呢?就用第40位數字小試牛刀。
計算第40個數就用了21秒,在沒有緩存的情況下,計算第1000個數字將花費幾天時間。
四、生成器
生成器是Python中功能強大的構造,可以高效地處理大量數據。假設你有一個10GB的日誌文件,記錄了某個軟體崩潰時的情況。為了找出問題所在,你必須在Python中高效地對其進行篩選。
最糟糕的方法是讀取整個文件,但由於你一行一行地查看日誌,所以不需要一次性讀取全部10GB的數據,只需一次讀取一小部分。這就是你可以使用生成器的地方
在上面,我們定義了一個生成器,每次只疊代日誌文件中的1024行,因此最後的for循環非常高效。在for循環的每次疊代中,內存中只有1024行文件,先前的塊在內存中用完即棄,而其餘的塊只在需要時加載。
生成器的另一個特性是能夠使用next函數一次生成一個元素,即使是在循環之外。下面,我們將定義一個快速生成斐波那契數列的函數。
要創建生成器,只需調用一次該函數並在生成的對象上調用next函數。
五、上下文管理器
您一定已經使用上下文管理器很長時間了。它們允許開發人員有效地管理資源,如文件、資料庫和網絡連接。它們自動打開和關閉資源,從而生成清晰且無錯誤的代碼。
但是,使用上下文管理器和編寫自己的上下文管理器之間有很大的區別。如果處理得當,它們允許您在原始功能的基礎上抽象出大量樣板代碼。
一個常見的自定義上下文管理器的例子是計時器,代碼如下:
上面,我們定義了一個TimerContextManager類,它將作為未來的上下文管理器。它的__enter__方法定義了使用with關鍵字進入上下文時發生的情況。在本例中,__enter__方法 用於啟動計時器;在__exit__中,我們離開上下文,停止計時器,並報告經過的時間。
以下是一個更複雜的示例,它可以鎖定資源,使它們一次只能被一個進程使用。
原文標題:
5 Signs You've Become an Advanced Pythonista Without Even Realizing It
原文連結:
https://towardsdatascience.com/5-signs-youve-become-an-advanced-pythonista-without-even-realizing-it-2b1dd7ef57f3