日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

decorators 参数_Python Decorators(二):Decorator参数

發布時間:2023/12/10 python 51 豆豆
生活随笔 收集整理的這篇文章主要介紹了 decorators 参数_Python Decorators(二):Decorator参数 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Python Decorators II: Decorator Arguments

October 19, 2008

(本文是(Python3之模式和用法)一書的章節節選第二部分,點擊閱讀第一部分)

回顧:不含參數的decorators

在前文中,我介紹了如何使用不含參數的decorators,并使用類來實現。因為我發現這樣做更容易接受。

如果創建了一個無參decorator,被decorated的函數被傳至構造器,每次調用decorated函數時就會調用__call__()方法:

class decoratorWithoutArguments(object):

def __init__(self, f):

"""

If there are no decorator arguments, the function

to be decorated is passed to the constructor.

"""

print "Inside __init__()"

self.f = f

def __call__(self, *args):

"""

The __call__ method is not called until the

decorated function is called.

"""

print "Inside __call__()"

self.f(*args)

print "After self.f(*args)"

@decoratorWithoutArguments

def sayHello(a1, a2, a3, a4):

print 'sayHello arguments:', a1, a2, a3, a4

print "After decoration"

print "Preparing to call sayHello()"

sayHello("say", "hello", "argument", "list")

print "After first sayHello() call"

sayHello("a", "different", "set of", "arguments")

print "After second sayHello() call"

decorated函數的所有參數會被傳至__call__()。輸出結果是:

Inside __init__()

After decoration

Preparing to call sayHello()

Inside __call__()

sayHello arguments: say hello argument list

After self.f(*args)

After first sayHello() call

Inside __call__()

sayHello arguments: a different set of arguments

After self.f(*args)

After second sayHello() call

注意,__init__()是唯一一個被調用執行decoration的方法,每次調用decorated的sayHello()時就會調用__call__()。

含有參數的decorators

現在讓我們來修改上面的代碼,看看向decorator加入參數后結果是什么。

class decoratorWithArguments(object):

def __init__(self, arg1, arg2, arg3):

"""

If there are decorator arguments, the function

to be decorated is not passed to the constructor!

"""

print "Inside __init__()"

self.arg1 = arg1

self.arg2 = arg2

self.arg3 = arg3

def __call__(self, f):

"""

If there are decorator arguments, __call__() is only called

once, as part of the decoration process! You can only give

it a single argument, which is the function object.

"""

print "Inside __call__()"

def wrapped_f(*args):

print "Inside wrapped_f()"

print "Decorator arguments:", self.arg1, self.arg2, self.arg3

f(*args)

print "After f(*args)"

return wrapped_f

@decoratorWithArguments("hello", "world", 42)

def sayHello(a1, a2, a3, a4):

print 'sayHello arguments:', a1, a2, a3, a4

print "After decoration"

print "Preparing to call sayHello()"

sayHello("say", "hello", "argument", "list")

print "after first sayHello() call"

sayHello("a", "different", "set of", "arguments")

print "after second sayHello() call"

從輸出結果可以看到,加入參數使程序執行發生了很大變化。

Inside __init__()

Inside __call__()

After decoration

Preparing to call sayHello()

Inside wrapped_f()

Decorator arguments: hello world 42

sayHello arguments: say hello argument list

After f(*args)

after first sayHello() call

Inside wrapped_f()

Decorator arguments: hello world 42

sayHello arguments: a different set of arguments

After f(*args)

after second sayHello() call

現在decoration方法調用構造器,然后就馬上調用__call__(),后者只能包含一個參數(函數對象)且返回替代原有函數的decorated函數對象。注意當前decoration期間__call__()僅被調用一次,此后從__call__()返回的decorated函數就可以在實際調用中使用了。

雖然這種機制有一定合理性—構造器在這里可獲取decorator參數,但__call__()對象不能再作為decorated函數使用了。因此你必須使用__call__()執行decoration—可能第一次遇到這種與無參情況截然不同的方式你會比較吃驚,何況還必須編寫和無參decorator完成不同的代碼。

含decorator參數的decorator函數

最后,讓我們看一個更復雜一點的decorator函數實現,它需要你處理所有細節:

def decoratorFunctionWithArguments(arg1, arg2, arg3):

def wrap(f):

print "Inside wrap()"

def wrapped_f(*args):

print "Inside wrapped_f()"

print "Decorator arguments:", arg1, arg2, arg3

f(*args)

print "After f(*args)"

return wrapped_f

return wrap

@decoratorFunctionWithArguments("hello", "world", 42)

def sayHello(a1, a2, a3, a4):

print 'sayHello arguments:', a1, a2, a3, a4

print "After decoration"

print "Preparing to call sayHello()"

sayHello("say", "hello", "argument", "list")

print "after first sayHello() call"

sayHello("a", "different", "set of", "arguments")

print "after second sayHello() call"

輸出結果為:

Inside wrap()

After decoration

Preparing to call sayHello()

Inside wrapped_f()

Decorator arguments: hello world 42

sayHello arguments: say hello argument list

After f(*args)

after first sayHello() call

Inside wrapped_f()

Decorator arguments: hello world 42

sayHello arguments: a different set of arguments

After f(*args)

after second sayHello() call

decorator函數的返回值必須是一個封裝待decorated函數的函數。也就是說,Python會保存返回函數然后在decoration期間調用,并傳遞待decorated函數。這也是為何有三層函數的原因:里面那個函數才是被替換的。

由于閉包,wrapped_f()有權訪問decorator參數arg1, arg2和arg3,而無需像在class版本中那樣顯式存儲它們。然而,我也是在這里發現了“顯勝于隱(explicit is better than implicit)”。即使該函數版本看起來要更加簡潔緊湊,但我發現還是類版本容易理解,當然也就容易修改和維護。

下一節內容

在下一節中我會給出decorators的一些實例—基于Python開發的build system—然后在最后一節討論類decorators。

總結

以上是生活随笔為你收集整理的decorators 参数_Python Decorators(二):Decorator参数的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。