Python學習之路 裝飾器(3)

2021-09-28 14:29:28 字數 2650 閱讀 4177

上兩篇提到的裝飾器的例子中,被修飾的函式沒有引數,那麼如果修飾帶引數的裝飾器又該如何書寫呢?

#coding=utf-8

def f1(func):

print('in f1')

def f1_inner():

print('in f1_inner')

func()

return f1_inner

@f1def f(a,b):

print('in f')

if __name__ == '__main__':

a,b = 1,2

f(a,b)

結果:in f1

traceback (most recent call last):

file "e:/sourceinsightpro/python_code/16點14分/zhuangshiqi2.py", line 16, in f(a,b)

typeerror: f_inner() takes 0 positional arguments but 2 were given

首先f在定義是需要兩個引數,因此在呼叫的時候傳入兩個引數,但是結果卻報錯,提示16行錯誤:f_inner()不需要位置引數卻傳給了兩個引數。

原因是裝飾器f1修飾函式f,利用閉包的語句實現就是:f = f1(f),這句執行後f1返回的是f1_inner的引用,而f本身傳入了兩個引數,f1_inner在定義時卻沒有引數,因此才出現了這個錯誤,因此,在f1_inner定義時需要定義形參。即**如下所示:

def f1(func):

print('in f1')

def f1_inner(a,b):

print('in f1_inner')

func()

return f1_inner

@f1def f(a,b):

print('in f')

if __name__ == '__main__':

a,b = 1,2

f(a,b)

結果:in f1

traceback (most recent call last):

in f1_inner

file "e:/sourceinsightpro/python_code/16點14分/zhuangshiqi2.py", line 16, in f(a,b)

file "e:/sourceinsightpro/python_code/16點14分/zhuangshiqi2.py", line 7, in f_inner

func()

typeerror: f() missing 2 required positional arguments: 'a' and 'b'

在f1_inner中加上形參後發現依舊報錯,提示是第六行:函式f丟了兩個位置引數

原因是在呼叫函式f(a,b)後,f是作為實參傳入f1中,但是在f1_inner中呼叫func(即f)時卻沒有傳入引數,因此才出現了這樣的錯,修改後的完整**如下:

#coding=utf-8

def f1(func):

print('in f1')

def f1_inner(a,b):

print('in f1_inner,a:%d b:%d' % (a,b))

func(a,b)

return f1_inner

@f1def f(a,b):

print('in f')

print('a:%d b:%d' % (a,b))

if __name__ == '__main__':

a,b = 1,2

f(a,b)

結果:in f1

in f1_inner,a:1 b:2

in f

a:1 b:2

至此實現了裝飾器修飾帶引數的函式。但是卻引入乙個問題:上面例子中f需要兩個引數,因此在f1_inner定義時也宣告了兩個形參。但是這樣的書寫形式太麻煩,耦合性太大,能否換一種簡便的書寫形式呢?此時便可以使用之前函式中的學到的:*args和**kwargs。看下面的**:

def f2(func):

print('in f2')

def f2_inner(*args,**kwargs):

print('in f2_inner')

print(args)

print(kwargs)

func(*args,**kwargs)

return f2_inner

@f2def f(a,b,*args,**kwargs):

print('in f')

print(a)

print(b)

print(args)

print(kwargs)

if __name__ == '__main__':

a,b = 1,2

f(a,b,'hello','world',c = 10,d = 20)

結果:in f2

in f2_inner

(1, 2, 'hello', 'world')

in f12

('hello', 'world')

Python學習之路 裝飾器(1)

裝飾器本身是利用閉包實現的,因此只有真正學會了閉包中的知識點才能完全理解裝飾器的語法。試想乙個問題 在乙個工程中有乙個函式func 現在有乙個需求是func 現在本身不能滿足的,因此需要重新實現func 的功能。這是正常的思路,也是可行的,但是卻違背了開發中的 開放 封閉 原則。封閉 函式本身的功能...

Python學習之路 裝飾器(2)

coding utf 8 def f1 func print in f1 def f1 inner print in f1 inner func return f1 inner def f2 func print in f2 def f2 inner print in f2 inner func r...

Python學習之路 裝飾器(4)

函式通常都是帶有返回值的,當裝飾器修飾帶有返回值的函式時該怎麼實現呢?coding utf 8 def f1 func print in func def f1 inner print in f1 inner value func return value return f1 inner f1def...