詳解Python閉包,裝飾器及類裝飾器

2021-09-11 17:54:12 字數 3124 閱讀 2885

在專案開發中,總會遇到在原**的基礎上新增額外的功能模組,原有的**也許是很久以前所寫,為了新增新功能的**塊,您一般還得重新熟悉源**,稍微搞清楚一點它的邏輯,這無疑是一件特別頭疼的事情.今天我們介紹的python裝飾器就能夠很好的解決這類問題.

1.閉包函式

閉包比較簡單,直接上**

def _sum():

num1 = 1

num2 = 2

def count():

num3 = 3

return num1 + num2 + num3 # a: - 外部變數

return count

滿足閉包的主要兩點:函式內部定義的函式;引用了外部變數但非全域性變數。

2.裝飾器

有了閉包函式的概念,我們再去理解裝飾器會相對容易一些。

python裝飾器本質上就是乙個函式,它可以讓其他函式在不需要做任何**變動的前提下增加額外的功能,裝飾器的返回值也是乙個函式物件(函式的指標)

。裝飾器函式的外部函式傳入我要裝飾的函式名字,返回經過修飾後函式的名字;內層函式(閉包)負責修飾被修飾函式。從上面這段描述中我們需要記住裝飾器的幾點屬性,以便後面能更好的理解:

"""

裝飾器實質:就是乙個函式

引數:是要被裝飾的函式

返回:裝飾完的函式名

作用:為已有的功能模組新增額外的功能

特點:不需要修改原始碼(源**不做任何操作)

"""

2.1 函式裝飾器

我們以為函式新增計時功能為例講解 

def test(func):

print "test parameter pointer: %s" % func.__name__

def test(*args, **kwargs):

start_time = time.time()

func()

end_time = time.time()

print end_time-start_time

return test

@test

def my_log():

time.sleep(0.8)

my_log()

在上面的例子裡,my_log

是我要裝飾器的函式,我們要給my_log函式新增程式執行計時的功能.@test這個語法相當於 執行 my_log= test(func), 為my_log函式裝飾並返回物件指標。在裝飾器函式test中,該函式傳入func引數(實質是被裝飾函式my_log).在首次呼叫my_log()時,分倆步執行:1.先執行裝飾器test[類似於test(my_log)],此時,func指向my_log所在的記憶體位置,而由於test裝飾器函式返回內建函式test,所以被裝飾函式my_log指向內建函式test所在的記憶體位置.

2.當指行完裝飾器函式後,呼叫my_log函式,此時的my_log函式實質是內建函式test,也就是呼叫了test(),從而在執行func()[即在此處才是真正呼叫了原函式my_log]函式.這就是乙個簡單裝飾器的全部流程,主要的就是函式指標所指的記憶體位置發生變化.

執行結果:

>>>/usr/bin/python2.7 /home/jianping/work/tax_punish/test2.py

>>>test parameter pointer: my_log   

# 此處即可發現裝飾器中的func函式指向了被裝飾函式my_log的記憶體位置

>>>0.800601959229

類方法的函式裝飾器 : 類方法的函式裝飾器和函式的函式裝飾器類似。

import time

def decorator(func):

start_time = time.time()

func(me_instance)

end_time = time.time()

print(end_time - start_time)

class method(object):

@decorator

def func(self):

time.sleep(0.8)

p1 = method()

對於類方法來說,都會有乙個預設的引數

self

,它實際表示的是類的乙個例項,所以在裝飾器的內部函式

也要傳入乙個引數 - 

me_instance

就表示將類的例項

p1傳給

,其他的用法都和函式裝飾器相同。

前面我們提到的都是讓 函式作為裝飾器去裝飾其他的函式或者方法,那麼可不可以讓 乙個類發揮裝飾器的作用呢?答案肯定是可以的,一切皆物件嚒,函式和類本質沒有什麼不一樣。類的裝飾器是什麼樣子的呢?

class decorator(object):

def __init__(self, f):

self.f = f

def __call__(self):

print("decorator start")

self.f()

print("decorator end")

@decorator

def func():

print("func")

func()

這裡有注意的是:__call__()是乙個特殊方法,它可將乙個類例項變成乙個可呼叫物件:

p = decorator(func) # p是類decorator的乙個例項

p() # 實現了__call__()方法後,p可以被呼叫

posted @ 2018-10-25 14:18

編輯收藏

詳解Python閉包,裝飾器及類裝飾器

在專案開發中,總會遇到在原 的基礎上新增額外的功能模組,原有的 也許是很久以前所寫,為了新增新功能的 塊,您一般還得重新熟悉源 稍微搞清楚一點它的邏輯,這無疑是一件特別頭疼的事情 今天我們介紹的python裝飾器就能夠很好的解決這類問題 閉包函式 閉包比較簡單,直接上 def sum num1 1 ...

Python閉包 裝飾器

閉包 legb法則 所謂閉包,就是將組成函式的語句和這些語句的執行環境打包一起時得到的物件 閉包最重要的價值在於封裝上下文環境 下面有個列子來解釋下閉包 列 deffunx x print 開始 deffuny y returnx y print 結束 returnfuny x funx 4 pri...

python 閉包 裝飾器

2.閉包格式 return bar 返回內嵌函式 in test print in 3.使用原理 4.總結 二 裝飾器 2.格式 return test in 閉包函式返回內嵌函式 test aa test aa 裝飾 def aa 這兒如果有引數,test in也必須有一樣的引數,test in中...