1、reduce是python中的内建函數,它是一個二進制操作函數,他用來将一個資料集合中的所有資料進行下列操作:用傳給reduce中的函數 func()(必須是一個二進制操作函數)先對集合中的第1,2個資料進行操作,得到的結果再與第三個資料用func()函數運算,最後得到一個結果。

2、callable是檢查對象object是否可調用。如果傳回True,object仍然可能調用失敗;但如果傳回False,調用對象ojbect絕對不會成功。
3、lambda通常是在需要一個函數,但是又不想費神去命名一個函數的場合下使用,也就是指匿名函數。它隻是一個表達式,而def則是一個語句。lambda表達式運作起來像一個函數,當被調用時建立一個架構對象。起到一個函數速寫的作用,允許在代碼内嵌入一個函數的定義。
下面開始正式開始學習裝飾器,學習裝飾器的第一個要了解的是比較基礎的一個概念,用python的都是知道了,但是這裡還是提一下,python中一切皆是對象,是以函數也一定是一個對象,被函數名所引用,這樣函數名就可以被作為一個參數賦給其他變量,或者作為參數傳給其他函數,比如:
func作為一個參數傳給了para,就相當于給func起了一個别名,執行para就相當與執行func函數,可以看到列印的值就是func的值,将函數作為參數傳給另一個參數也是一樣的,如下:
第二個需要了解的可能有些人并不很清楚,那就是閉包原則,所謂閉包,就是将組成函數的語句和這些語句的執行環境打包在一起時,得到的對象,為了了解這個概念,先來看一個例子:
我們是調用的call.py的方法,但是列印輸出确是dec.py檔案定義的參數内容,這就涉及到解釋器查找變量的順序了,首先查找本地函數内部,然後查找上層,再上層,一直到最外層,再查找全局變量,再查找内置子產品,在這期間,如果一旦查找到了該參數,就會終止查詢,是以上面的代碼會現在本檔案逐層向上進行查詢,查到了就是dec.py的參數,如果換一種調用方式就不同了,如下:
到這裡,就可以提出閉包的作用了,閉包所要做的事就是封存上下文的環境,使之後的執行仍然可以使用閉包内的内容,上面的代碼,當将called傳入call函數時,called已經将執行環境封存了,在call内部再調用called的函數時called函數取的其實是被封存的執行函數的參數。
裝飾器就用到了閉包的概念,看一下下面這個函數:
我們都知道,一旦一個函數執行結束,局部變量就會被回收,test_sum=dec()這一行執行完之後,按道理num這個變量就會被回收掉了,但是為什麼執行test_sum()還會傳回5050?這個其實就是在傳回sum對象時已經成為了一個閉包,上下文已經被封存了,是以我們在執行test_sum函數時還可以取得上下文。
然後來說下裝飾器,裝飾器可以對一個函數、方法或者類進行加工,概括的講,裝飾器的作用就是為已經存在的對象添加額外的功能。較為經典的有插入日志、性能測試、事務處理等。裝飾器是解決這類問題的絕佳設計,有了裝飾器,我們就可以抽離出大量函數中與函數功能本身無關的雷同代碼并繼續重用,比如,我們希望在一個函數執行前後列印執行開始和執行完成,依賴上面的對象可以作為參數傳入的前提,那個上面的函數可以改為這樣。
可以看到執行test_sum=dec(sum)會傳回一個sum_log對象,并形成一個閉包,是以下面在執行test_sum(1,101)時func仍然是之前傳入的sum函數,這就像在原來的函數基礎上增加了一層裝飾,但是這樣寫是不是有些麻煩,于是python提供了一種更優雅的寫法,被稱為文法糖,就是用@這個符号:
這樣看起來是不是簡單優雅多了,雖然這種寫法第一眼看上去不了解,但是隻要搞清楚它的實作原理就不難了,它仍然是執行的我們上面講到的操作,即sum=dec(sum),sum(1,101)。
可能有人會問,既然裝飾器也是函數,那麼我可以為裝飾器傳參數嗎?答案一定是可以的。
看上面的代碼dec做了兩次傳回,内部傳回的是sum_log,主要是将sum_log函數的上下文做封裝,傳回dec_para對象是将dec_para的上下文做封裝,這樣,我們在執行sum()的時候就可以使用上下文的參數了。而執行sum(1,101)的時候其實就相當于執行sum=dec(str)(sum),
sum(1,101)一樣,這樣,裝飾器我們能就能了解的已經很清楚了。
但是了解了裝飾器以後,我們一定會有這樣的疑問,在裝飾之後,我們執行的還是原來的函數嗎?sum是否還是sum函數?我們可以試一下,将函數的名字打出來:
看結果,傳回的函數名是sum_log,這樣有些時候會有問題,python提供了一個叫wraps的decorator來消除這樣的副作用,是以,可以把上面的代碼改成這樣:
這下,傳回的函數名就又是sum了。
那麼有時候我們并不确定裝飾器是否會傳入參數,碰到這種情況該如何進行相容呢?這裡介紹一個函數叫callabe(func),這個函數會判斷參數是否是可調用的,我們用這個來進行判斷來相容裝飾器不确定傳參的情況,代碼可以改動為如下:
這樣,我們定義的裝飾器就同時支援傳參與不傳參兩種情況了,這樣運用就會更加靈活。