python閉包和裝飾器

2021-08-04 06:48:40 字數 2883 閱讀 7090

要理解裝飾器,就要明白閉包;

要明白閉包,首先就要從高階函式和作用域說起;

說道作用域,一般會談到legb規則。所謂的legb:

l:locals,當前命名空間(區域性作用域)

e:enclosing,外部函式的命名空間(外部作用域)

g:global,全域性的命名空間

b:bulit in,內建的命名空間

平常的變數命名並賦值如

x=4

def f():

print(x)

print(x)#正確執行

f()#錯誤

則x是乙個區域性的變數,只有在同一作用域的**塊才能呼叫到x。直接列印x的值是可以的。但是通過呼叫f來列印是不能的,因為其中的x是形參,並沒有指向記憶體中的單元。也就是方法f中的x不在同乙個作用域。

但是,如果在方法f中用global宣告變數x

x = 4

def f():

global x

print(x)

f()

通過這樣的方式,將方法x宣告為全域性變數,則方法中變數x的就是方法外的變數x。

而內建的命名空間,就是python預設支援的函式,也稱為內建函式,比如說:

abs()#求絕對值

add()#兩數相加

sum()#求和

呼叫這些方法不需要提前宣告,可以直接使用。而外部作用域,一般是用在閉包中的,談到閉包,還要講一講高階函式。

高階函式有兩個特點:

1、函式名能夠作為引數傳遞到到函式的內部

2、函式名能夠作為返回值

也就是說,我們能夠把乙個普通的函式作為引數,在另乙個函式體內返回,通過變數接收後呼叫來實現呼叫這個普通函式。

def f():

print("haha")

def fn(f):#函式f通過引數傳遞到fn

print("hehe")

return f

b = fn()

b()

如此,fn就是乙個高階函式。f通過引數傳遞到fn的內部然後返回。當執行b=fn()時,print語句被執行,輸出其中內容。而後返回了乙個函式物件,用變數b接受函式物件後,就可以對b進行函式的呼叫了。

函式是可以進行巢狀建立的:

def fn():

x = 4

def f():

print(x)

return f

a = fn()

a()

函式的巢狀其實沒啥好說的,關鍵是其中的x的作用域問題。在函式f的函式體裡面,並沒有宣告變數x,也沒有傳參,為什麼能夠取到x的值?

這也就是上面說的legb規則了。當執行print時,首先查詢當前的區域性作用域,發現沒有找到符合的,於是就去外部作用域找。變數x處於的正是外部作用域。如果在外部作用域還找不到,就去全域性作用域中找,再找不到,就去內建作用域中找。內建作用域中找不早,就會報錯。

當執行函式fn()時,只有執行了return 語句,函式f並沒有被呼叫。也就是說,呼叫函式a()才是對函式f的呼叫,換乙個角度,函式f是在外面的執行的,但是當執行了函式fn後,變數x的內容已經被清空了,那麼在外面呼叫函式f時為什麼能夠取到變數x的值呢?

這就是涉及到的閉包了。函式fn裡return的函式f就是乙個閉包函式。

閉包的定義:如果在乙個內部函式裡,對在外部作用域的變數進行引用,那麼內部函式就被認為是閉包。
所以說,閉包是函式的定義加上定義時的環境。

如果你要對已經提交的成品**的某些函式新增功能,或者對多個函式新增相同的功能,你會怎麼做?

如果直接修改源**,那麼就會對某些呼叫該函式的**產生影響。如果該**已經被執行,修改**就會產生錯誤,導致軟體停止執行。在實際生產是很要命的。

我們一步一步思考。

1、首先,可以利用高階函式的特性,你可以選擇建立乙個函式,然後在該函式體內呼叫功能函式,然後用功能函式相同的變數接收。

def func(f):

def fn():

print("yingyingying")

f()#呼叫的功能函式

return f

f = func()

f()

從原功能函式來講,函式func就是乙個裝飾函式,對函式f進行了裝飾。python提供了一種語法來進行這樣的裝飾行為,就是裝飾器

def func(f):

def fn():

print("yingyingying")

f()return fn()

@func

def f():

#功能**

f()

其中,@func就是宣告裝飾器函式,它的意義就是同上面的 f = func(),它的作用就是將功能函式中的**轉移到函式func中執行。若功能函式f帶引數,則在裝飾器函式中的fn中傳遞功能函式所需的引數。

2、帶引數的裝飾器

如果裝飾器函式需要引數,怎麼辦呢?那麼,就要用到閉包了。

def func_decorate(x):

def func(f):

def fn():

print("yingyingying")

print(x)

return fn

return func

@func_decorate(3)

def f():

#功能**

f()

其中的關鍵:

1、儲存外部變數x,返回閉包函式func

2、f = func()

python裝飾器和閉包

下面幾個部落格有裝飾器的講解,也包含了裝飾器幾種情況的例子,比如說被裝飾的函式帶引數,裝飾器本身帶引數等。理解python中的裝飾器 python裝飾器學習 例子 其實裝飾器跟設計模式中的裝飾器模式基本一樣,就是在已有的函式上新增新的功能,這也是自己對裝飾器的一點簡陋的理解了。下面是自己寫的簡單例子...

python 閉包和裝飾器

閉包的寫法,兩層函式的巢狀,外部函式返回內部函式的引用,外層函式都帶引數 def 外層函式的名稱 引數 def 內層函式的名稱 pass return 內層函式的引用 def set fun func func 254 defcall fun nonlocal func 修改外層函式的值,並且內部函...

Python 閉包和裝飾器

裝飾器函式裝飾器 類裝飾器 functools.wraps 簡介def outer func number definner func inner number return number inner number return inner func 給外部函式複製,20傳遞給number,並返回內...