1. 程式人生 > >Python裝飾器的函數語言程式設計

Python裝飾器的函數語言程式設計

        Python的修飾器的英文名叫Decorator,當你看到這個英文名的時候,你可能會把其跟Design Pattern裡的Decorator搞混了,其實這是完全不同的兩個東西。雖然好像,他們要乾的事都很相似——都是想要對一個已有的模組做一些“修飾工作”,所謂修飾工作就是想給現有的模組加上一些小裝飾(一些小功能,這些小功能可能好多模組都會用到),但又不讓這個小裝飾(小功能)侵入到原有的模組中的程式碼裡去。但是OO的Decorator簡直就是一場惡夢,不信你就去看看wikipedia上的詞條(Decorator Pattern)裡的UML圖和那些程式碼,這就是我在《 從面向物件的設計模式看軟體設計

》“餐後甜點”一節中說的,OO鼓勵了——“厚重地膠合和複雜層次”,也是《 如此理解面向物件程式設計》中所說的“OO的狂熱者們非常害怕處理資料”,Decorator Pattern搞出來的程式碼簡直就是OO的反面教程。

        Python 的 Decorator在使用上和Java/C#的Annotation很相似,就是在方法名前面加一個@XXX註解來為這個方法裝飾一些東西。但是,Java/C#的Annotation也很讓人望而卻步,太TMD的複雜了,你要玩它,你需要了解一堆Annotation的類庫文件,讓人感覺就是在學另外一門語言。

        而Python使用了一種相對於Decorator Pattern和Annotation來說非常優雅的方法,這種方法不需要你去掌握什麼複雜的OO模型或是Annotation的各種類庫規定,完全就是語言層面的玩法:一種函數語言程式設計的技巧。如果你看過本站的《

函數語言程式設計》,你一定會為函數語言程式設計的那種“描述你想幹什麼,而不是描述你要怎麼去實現”的程式設計方式感到暢快。(如果你不瞭解函數語言程式設計,那在讀本文之前,還請你移步去看看《函數語言程式設計》) 好了,我們先來點感性認識,看一個Python修飾器的Hello World的程式碼。

Hello World

下面是程式碼:

檔名:HELLO.PY
123456789101112def hello(fn):def wrapper():print "hello, %s" % fn.__name__fn()print "goodby, %s" % fn.__name__return wrapper@hello
def foo():print "i am foo"foo()

當你執行程式碼,你會看到如下輸出:

1234[[email protected]]$ python hello.pyhello, fooi am foogoodby, foo

你可以看到如下的東西:

1)函式foo前面有個@hello的“註解”,hello就是我們前面定義的函式hello

2)在hello函式中,其需要一個fn的引數(這就用來做回撥的函式)

3)hello函式中返回了一個inner函式wrapper,這個wrapper函式回調了傳進來的fn,並在回撥前後加了兩條語句。

Decorator 的本質

對於Python的這個@註解語法糖- Syntactic Sugar 來說,當你在用某個@decorator來修飾某個函式func時,如下所示:

123@decoratordef func():pass

其直譯器會解釋成下面這樣的語句:

1func = decorator(func)

尼瑪,這不就是把一個函式當引數傳到另一個函式中,然後再回調嗎?是的,但是,我們需要注意,那裡還有一個賦值語句,把decorator這個函式的返回值賦值回了原來的func。 根據《函數語言程式設計》中的first class functions中的定義的,你可以把函式當成變數來使用,所以,decorator必需得返回了一個函數出來給func,這就是所謂的higher order function 高階函式,不然,後面當func()呼叫的時候就會出錯。 就我們上面那個hello.py裡的例子來說,

123@hellodef foo():print "i am foo"

被解釋成了:

1foo = hello(foo)

是的,這是一條語句,而且還被執行了。你如果不信的話,你可以寫這樣的程式來試試看:

123456def fuck(fn):print "fuck %s!" % fn.__name__[::-1].upper()@fuckdef wfg():pass

沒了,就上面這段程式碼,沒有呼叫wfg()的語句,你會發現, fuck函式被呼叫了,而且還很NB地輸出了我們每個人的心聲!

再回到我們hello.py的那個例子,我們可以看到,hello(foo)返回了wrapper()函式,所以,foo其實變成了wrapper的一個變數,而後面的foo()執行其實變成了wrapper()

知道這點本質,當你看到有多個decorator或是帶引數的decorator,你也就不會害怕了。

比如:多個decorator

1234@decorator_one@decorator_twodef func():pass

相當於:

1func = decorator_one(decorator_two(func))

比如:帶引數的decorator:

123@decorator(arg1, arg2)

相關推薦

Python裝飾

cor 動態 定義 增加 方式 休眠 混亂 一秒 變量 裝飾器函數 這裏定義了一個func函數,打印‘我是func函數’ def func(): print(‘我是func函數‘); time.sleep(1); 假設,想要在func()函數的基礎

Python(九)語法 語言程式設計(函式作為返回值,lambda)

函式作為返回值 高階函式除了可以接受函式作為引數外,還可以把函式作為結果值返回。 我們來實現一個可變引數的求和。通常情況下,求和的函式是這樣定義的: >>> def sum(*args): ... s=0 ... for x in args: ... s=s+x

Python(八)語法 語言程式設計(map/reduce/filter/sorted)

map map()函式接收兩個引數,一個是函式,一個是Iterable,map將傳入的函式依次作用到序列的每個元素,並把結果作為新的Iterator返回。,簡單點說就是讓每個元素執行函式,如下對L中每個元素求平方 >>> def f(x): ... return x*x

Python學習筆記 -- 語言程式設計之高階函式

函數語言程式設計 函數語言程式設計(Functional Programming),是一種抽象程度很高的程式設計正規化,純粹的函數語言程式設計語言編寫的函式沒有變數。因此,任意一個函式,只要輸入是確定的,輸出就是確定的。 函數語言程式設計是一種"程式設計正規化"(pro

python學習-基礎-語言程式設計

高階函式 # 高階函式 # 函式本身也可以賦值給變數,即:變數可以指向函式。 # 既然變數可以指向函式,函式的引數能接收變數,那麼一個函式就可以接收另一個函式作為引數,這種函式就稱之為高階函式。 def add3(x, y, f): return f(x) + f(

(資料科學學習手札101)funcy:Python中的語言程式設計百寶箱

> 本文示例檔案已上傳至我的`Github`倉庫[https://github.com/CNFeffery/DataScienceStudyNotes](https://github.com/CNFeffery/DataScienceStudyNotes) # 1 簡介   我們在使用`Python`完成

python語言程式設計3(裝飾的深入理解)

一、什麼是裝飾器 1、python中裝飾器可以理解為AOP程式設計,有點類似Spring中的註解,在不改變原函式或類的基礎上,對函式或類新增額外(自己需求補充)的功能。 2、裝飾器本質上是一個函式,該函式用來處理其他函式,它可以讓其他函式在不需要修改程式碼的前提下增加額外的功能,裝飾器的返回值也是

Python裝飾語言程式設計

一、函數語言程式設計 “函數語言程式設計”同“面向物件程式設計”,“面向過程程式設計”一樣是一種程式設計正規化,它屬於”結構化程式設計”的一種,主要思想是把運算過程儘量寫成一系列巢狀的函式呼叫。相比於面向物件,函數語言程式設計的最大優點在於將計算機運算看做是數

Python語言程式設計(高階函式 返回函式 匿名函式 裝飾 偏函式)

函數語言程式設計 將業務邏輯細化,抽象,封裝成一個個功能函式,並藉助語言自帶的高階函式api,將整個業務流程轉化為函式之間的相互呼叫,這就是函數語言程式設計。 對比:將業務邏輯細化,抽象,封裝成一個個物件,並藉助語言,庫,元件,框架等,將整個業務流程轉化為

python語言程式設計(三)裝飾、偏函式

1. 裝飾器 由於函式也是一個物件,而且函式物件可以被賦值給變數,所以,通過變數也能呼叫該函式。 >>>def now():        print('2015-3-25') >>>f = now >>>f() 201

Python裝飾語言程式設計

        Python的修飾器的英文名叫Decorator,當你看到這個英文名的時候,你可能會把其跟Design Pattern裡的Decorator搞混了,其實這是完全不同的兩個東西。雖然好像,他們要乾的事都很相似——都是想要對一個已有的模組做一些“修飾工作”,所謂修

語言程式設計之函式返回值&裝飾

一、函式返回值 1.什麼是函式返回值 顧名思義,函式返回值,就是一個函式的返回值,是一個函式名的情況 2.閉包 以計算多個數之和為例: 方法一:直接呼叫函式 def cacl_sum(*args): all_sum = 0 for i

python全棧開發從入門到放棄之裝飾

def return app 不改變 art sdl 兩個 time() 必須 1、函數名可以當作函數的參數 1 import time 2 def timmer(func): 3 #函數名可以當做函數的參數 4 def inner(): 5

python語言程式設計

一、python中or和and的使用 1、使用方式 result = a or b result = a and b 複製程式碼 2、or計算規則 當a為真的時候就直接返回a的值,否則返回b的值 3、and計算規則 當a為真的時候返回b,當a為假

Python 語言程式設計(待續)

函數語言程式設計 把計算視為函式而非指令 純函數語言程式設計:不需要變數,沒有副作用,測試簡單 支援高階函式,程式碼簡潔 高階函式——將函式作為引數傳入函式 map() 把函式依次作用在 list 的每個元素上,得到一個新的list並返回 [

python學習——裝飾

復雜 完美 inner python python開發 之前 六大原則 修改 參數 一、裝飾器函數的作用是什麽   答:裝飾器函數是在不修改原函數及其調用方式的情況下對原函數功能進行擴展   對於搞python開發的人來說,函數占據了至關重要的地位。都說學好函數你就可以

聰哥哥教你學Python語言程式設計

今天主要圍繞這麼幾個方面談談函數語言程式設計? 1.高階函式 2.返回函式 3.匿名函式 4.裝飾器 5.偏函式 有人會有疑問,聰哥哥請問什麼是函數語言程式設計? 引用百度百科的話說: 函數語言程式設計是一種程式設計方式,它將電腦運算視為函式的計算。函式程式語言最重要

Python之路-Day08語言程式設計與內建函式

return可以返回任何值 當你在一個函式當中返回一個函式名的時候,其實返回的是這個函式在記憶體當中的地址,如果你用一個變數去接收它,然後以這個變數名執行的話,就會執行你返回的記憶體地址對應的那個函式. def test1(): print("in the test1")

python學習筆記03-python語言程式設計

1. 高階函式 1. 高階函式基礎 變數可以指向函式 函式名也是變數 高階函式允許傳入函式  #!/usr/bin/env python #將函式賦值給變數 A = abs print A(-10) #匯入__builtin__模組 import __builtin

Python之路Python作用域、匿名函式、語言程式設計、map函式、filter函式、reduce函式 Python之路Python作用域、匿名函式、語言程式設計、map函式、filter函式、reduce函式

Python之路Python作用域、匿名函式、函數語言程式設計、map函式、filter函式、reduce函式 一、作用域 return 可以返回任意值例子 def test1(): print("test1") def test(): print("te