Python 裝飾器與閉包

2021-10-06 01:45:25 字數 2386 閱讀 3191

python中的裝飾器真的是個很難理解的概念,以下只是我在學習過程中的一點淺見,學習交流。

在談裝飾器之前,不得不說一下閉包的概念。什麼是閉包呢?維基百科上是這麼講的——

在電腦科學中,閉包(英語:closure),又稱詞法閉包(lexical closure)或函式閉包(function closures),是引用了自由變數的函式。這個被引用的自由變數將和這個函式一同存在,即使已經離開了創造它的環境也不例外。

簡直不像人話。我們通過一小段**來感受一下閉包:

def foo():

a = 'free var'

def bar():

print(a)

return bar

**中有兩個函式:外函式foo()以及內函式bar(),這個巢狀函式就形成了乙個閉包。閉包是延伸了作用域的函式,它使得內函式bar()能夠訪問未在其函式體中定義的非全域性變數,未在函式定義體中定義的非全域性變數一般都是在巢狀函式**現。

形成閉包一般需要以下條件:

在乙個外函式中定義乙個內函式;

外函式的返回值是內函式的引用;

內函式裡運用了外函式的臨時變數。

裝飾器簡單來講是修改其他函式的功能的函式。裝飾器也是乙個閉包,只不過變數是被裝飾的另乙個函式。可以在裝飾器內部實現額外的功能,以增強被裝飾函式的行為,然後返回被裝飾的函式或者將其替換成乙個新的函式。

def inner(*args,**kwargs):

# function code

return func(*args,**kwargs)

return inner

裝飾器的語法糖@,使用方式:

def test(var):

pass

執行的過程:

有時候裝飾器本身需要使用一些引數,這時裝飾器在定義時需要三層函式。以下是乙個例子:

def logit(logfile='out.log'):

def logging_decorator(func):

# function code

return func(*args, **kwargs)

return logging_decorator

它實際上是對原有裝飾器的乙個函式封裝,並返回乙個裝飾器。我們可以將它理解為乙個含有引數的閉包。當我們使用@logit(logfile='out.log')呼叫的時候,python能夠發現這一層的封裝,並把引數傳遞到裝飾器的環境中。 

class logit(object):

def __init__(self, logfile='out.log'):

self.logfile = logfile

def __call__(self, func):

# function code

return func(*args, **kwargs)

def notify(self):

pass

這個實現有乙個附加優勢,在於比巢狀函式的方式更加整潔,而且包裹乙個函式還是使用跟以前一樣的語法。

裝飾器的引數也可以是乙個類,也就是說,裝飾器可以裝飾類:

import types

def deco(cls):

for key, method in cls.__dict__.items():

if isinstance(method, types.functiontype):

print(key, ':', method.__name__)

return cls

@deco

class test:

def __init__(self):

pass

def foo(self):

pass

1.裝飾器可以疊加使用,乙個被裝飾的函式可以使用多個裝飾器。

def func()

pass

2.裝飾器是匯入時執行的,而被裝飾的函式是明確呼叫時執行的。

3.自定義的裝飾器會改變被裝飾函式的元資訊,如docstring,__name__等,我們可以使用標準庫functools中的wraps函式來解決這個問題。wraps本身也是乙個裝飾器,它能把原函式的元資訊拷貝到裝飾器函式中,這使得裝飾器函式也有和原函式一樣的元資訊了。

from functools import wraps

def decorator_name(f):

@wraps(f)

def decorated(*args, **kwargs):

# function code

return f(*args, **kwargs)

return decorated

python閉包與裝飾器

首先閉包函式我的理解是,乙個函式內可以巢狀定義乙個函式,並將巢狀定義的函式返回 如果不返回執行完函式物件也就銷毀了 巢狀函式可以接收外部函式的引數,不同引數就可以變更巢狀函式的功能,返回不同功能的巢狀函式物件。以下是閉包函式簡單示例,如果inner函式不接收outer的引數x也就沒有意義了,一定要返...

Python閉包與裝飾器

一.閉包 如果乙個內嵌函式中引用了外部函式中的變數 非全域性變數 那麼該內嵌函式稱之為閉包 也就是將組成函式的語句和這些語句的執行環境打包在一起時,得到的物件 閉包滿足的三個條件 1.必須是內嵌函式 2.外層函式返回值是內嵌函式 3.內嵌函式引用外層函式變數 def funx x def funy ...

Python 閉包與裝飾器

在函式內部再定義乙個函式,並且內部這個函式用到了外邊函式的變數,那麼將內部函式以及用到的一些變數稱之為閉包。兩個函式巢狀,外層函式返回內層函式的引用,外層函式必須傳引數 外層函式不傳參相當於只定義內層函式,沒有什麼用。注意點 由於閉包引用了外部函式的區域性變數,則外部函式的區域性變數沒有及時釋放,消...