深入淺析Python 函式註解與匿名函式
函式註解與匿名函式
關於函式引數的定義,呼叫以及函式引數的內容,在下面的文章中已經做了初步的介紹,有需要的可以訪問進行了解:
Python 函式
函式註解
在編寫函式,當下肯定清楚函式如何使用的。若是函式較為複雜,過段時間,編寫者有可能需要花一段時間去重新瞭解函式的使用,那其他使用者也同樣會遇到這樣的困惑。
所以當編寫完函式後,可以為函式的引數新增一些額外的資訊。這裡給函式引數添加註解,能夠提示程式設計師如何正確使用這個函式。如下示例:
def add(x:int,y:int) -> int: '''Returns the sum of two numbers ''' return x + y
在這裡,Python 直譯器並不會對這些註解新增任何的語義(可能第三方工具和框架會)。它們並不會被型別檢查,執行的時候跟沒有添加註解前是沒有任何差距的。但若是有需要的人閱讀原始碼時,這些都能給閱讀者提供幫助。同時會出現在文件裡。
>>> help(add) Help on function add in module __main__: add(x: int,y: int) -> int Returns the sum of two numbers
函式註解只儲存於函式的 __annotations__ 屬性中。比如:
>>> add.__annotations__ {'x': <class 'int'>,'y': <class 'int'>,'return': <class 'int'>}
註解的主要用途還是文件。Python 並沒有型別宣告,當閱讀原始碼的時候,比較難知道傳遞什麼樣的引數給這個函式。這時候,註解就能夠給閱讀者更多的提示,能夠讓他們正確使用函式。
匿名函式
如何定義
在前面提及的文章中,講到了使用 def 定義一個函式。但若是函式能夠單行實現,這個時候可以考慮使用匿名函式(lambda 表示式)來實現這種功能。
當函式功能非常簡單,僅僅只是計算一個表示式的值時,就可以用 lambda 表示式來替代。比如:
>>> add = lambda x,y: x + y >>> add <function <lambda> at 0x0000021496CD98B8> >>> add(2,3) 5 >>> add('hello',' world') 'hello world'
其實使用 lambda 表示式跟下面的效果是一樣的:
>>> def add(x,y): ... return x + y ... >>> add(2,' world') 'hello world'
lambda 表示式主要運用的場景是排序或者資料 reduce:
>>> pairs = [(1,'one'),(2,'two'),(3,'three'),(4,'four')] >>> sorted(pairs,key=lambda pair: pair[1]) [(4,'four'),(1,'two')]
上面的例子就是用於排序列表元素,以列表元素元組的第二個元素進行排序。此處的元組的第二個元素是字串,關於字串的比較,先比較字串的首字元,首字元相同時,比較第二個字元,以此類推。
在這裡, four 與 one , f 比 o 排序更前,所以 four 排在 one 前面, three 和 two 首字元相同,比較的是第二個字元 h 和 w ,所以 three 排在 two 前面。
儘管 lambda 表示式能夠定義簡單函式,但其實是有限制的。只能指定單個表示式,它的值就是最後返回的值。即是不能包含其他的語言特性,包括多個語句、迭代以及異常處理等等。
捕獲變數值
如何在定義匿名函式時捕獲某些變數的值?現在,先看看以下示例程式碼的效果:
>>> x = 10 >>> a = lambda y: x+y >>> x = 20 >>> b = lambda y: x+y
在這裡,先猜猜 a(10) 和 b(10) 的結果?若覺得結果是 20 和 30 ,那就錯了:
>>> a(10) 30 >>> b(10) 30
產生上面的結果,是因為 lambda 表示式中的 x 是一個自由變數,它是在執行的時候繫結值,而不是在定義的時候就繫結,這裡跟函式的預設值引數定義是不同的。因此,在呼叫這個 lambda 表示式時, x 的值其實是執行時的值。例如:
>>> x = 10 >>> a(10) 20 >>> x = 20 >>> b(10) 30
若是向在匿名函式在定義時就捕獲值,可以將引數值定義為預設引數:
>>> x=10 >>> a = lambda y,x=x: x+y >>> x=20 >>> b = lambda y,x=x: x+y >>> a(10) 20 >>> b(10) 30
還有一個需要注意:假如想用迴圈或列表推導建立一個 lambda 表示式列表,期望函式能夠在定義時就記住每次的迭代值。以下的寫法是無法達到效果的:
>>> func = [lambda x: x+n for n in range(5)] >>> for f in func: ... print(f(0)) ...
這裡最終執行的結果,也是因為最終執行,n 的值其實是迭代的最後一個值。
修改函式,使其達到想要達到的效果,也是上面提及的預設值的做法:
>>> func = [lambda x,n=n: x+n for n in range(5)] >>> for f in func: ... print(f(0)) ...
現在使用預設值引數的形式,就能夠實現在定義時繫結所需的值。
參考資料
來源
[1] David M. Beazley;Brian K. Jones.Python Cookbook,3rd Edtioni.O'Reilly Media.2013.
[2] "4.7.6 Lambda Expressions".docs.python.org.Retrieved 23 February 2020.
總結
到此這篇關於Python 函式註解與匿名函式的文章就介紹到這了,更多相關Python 函式註解與匿名函式內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!