關於python中函數的思考

基本語言特性

函數是幾乎任何程序語言都支持的基本語言特性。然而,不同的語言對函數的看法卻是不同的,這不僅導致了函數在語言中的地位,也產生出了不同的編程風格。
在scheme語言中,函數與普通數據別無二致,所以自然而然的將函數作爲第一類對象,同時scheme更強函數式編程和函數遞歸,以追求計算的本質。
在java中,函數與普通數據是區分開的,即函數不能直接被傳遞,只能被包裹到類中再通過實例對象被傳遞,高度的強調面向對象編程。
在python中,函數也被當做第一類對象,支持少量的函數式編程風格,但依然以面向對象爲主。

關於第一類對象的思考

所謂第一類對象,就是指這樣的一種對象:

  • 可以賦值給變量
  • 可以傳參給函數
  • 可以從函數中傳出

第一句話其實已經包含了後兩句,所以它們可以概括爲一句話:類似23,'hello',True,instance這種可以賦值給變量的對象。

首先,我覺得編程語言應該將函數對象作爲第一類對象,這應該成爲編程語言的標準特性,函數對象和數字23沒有什麼區別,它們本質上都是數據,所以函數對象可以和普通數據一樣被各種操作。但在java中,函數對象被看成與普通數據是不同的,這一點我覺得並不合理。如果在java中要傳遞一個函數對象,還必須首先將它包裹到一個類中,寄宿到一個實例對象中才能傳遞。

其次,將函數作爲第一類對象,本來就是應該具有的語言特性,並不能說某種語言(如python)支持此特性,就覺得另一種不支持此特性的語言(如java)更差勁。

此外,支持此特性,可以讓我們以函數式風格編寫代碼,在某些場景下,比面向對象風格的代碼更有表達力和更好的封裝性。

函數的定義

在python中使用如下語句定義一個函數對象:

def add(x, y):
    print('this is function add')
    result = x + y
    return result

思考這個函數定義,它包含了幾方面的內容:

  • 使用python的關鍵字def,目的是告訴python解釋器後續是一個函數定義,以便使用Function類實例化一個函數對象。
  • 定義了add作爲函數對象的變量名,此時函數對象作爲第一類對象。
  • 定義了參數列表(x, y)
  • 定義了函數體
  • 定義了返回值result

一個函數被定義完畢,將會存放在堆上以便被共享調用。
因爲add是此函數的引用,add存在於此函數定義處的上下文環境中。

函數的使用

result = add(2, 3)
print(result)

函數是描述符對象

因爲函數是一個對象,python中內置了一個dir函數可以查看對象的所有屬性信息。
如果仔細的查看可以看到,每一個函數對象的dir結果中,都有一個__get__函數。
這表示:

  1. python內置的Fucntion類中肯定定義了此__get__函數。
  2. __get__函數可以解釋實例方法的執行流程,即爲啥調用實例方法的時候會自動傳遞self。

函數是語句集合的抽象

因爲一個函數體中包含多條語句,這些語句有着高度統一的目標,都想爲統一的目標貢獻自己的力量。不同目標的語句應該放在不同的函數中。函數作爲多條語句的抽象,而類又作爲多個函數的抽象,然後模塊又作爲多個類的抽象,這是一個層次關係,目的都是爲了提供良好的封裝以降低程序的複雜度,提升模塊化。

函數是執行單元

嚴格來說,語句纔是最小的執行單元,但是我們一般站在函數的角度來表達一個程序(因爲站在語句的角度的話,代碼量太大了)。當函數成爲一個線程的執行單元時,我們對程序的編寫就可以轉換成:如何合理的設計函數。這種思路傾向於函數式編程。
把函數作爲執行單元,還有一個特點是,程序的執行是按照函數棧執行的,我們可以中斷和恢複函數以實現協程異步。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章