獨家 | 5 個Python高級特性讓你在不知不覺中成為Python高手

數據派thu 發佈 2024-03-01T07:27:17.980475+00:00

作用域定義了 Python 解釋器在程序中查找名稱定義的順序。原文標題:5 Signs You've Become an Advanced Pythonista Without Even Realizing It。


你已經使用 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



關鍵字: