簡體   English   中英

如何在裝飾器中混合* args,** kwargs和命名參數

[英]How to mix *args, **kwargs and named arguments in decorator

我想創建一個自定義的裝飾器,稱為captain_hook 它應該存儲hooks (要在修飾的函數之前調用的函數)並調用它們:

def captain_hook(func):
    def closure(hooks=[], *args, **kwargs):
        for hook in hooks: 
            hook(*args, **kwargs)
        return func(*args, **kwargs)
    return closure

現在我可以說:

@captain_hook
def sum(a, b):
    return a+b
sum.__defaults__[0].append(lambda arg: sys.stdout.write(str(arg))) #this lambda function prints argument
sum(1, 2) #should write (1, 2) and return 3

問題是我無法將參數傳遞給closure ,導致args第一個元素錯誤地解壓縮到hooks參數: sum(1, 2)設置hook=1a=2b - undefined 我怎么做?

修改__defaults__是一種處理此問題的非常可疑的方法。 __defaults__用於參數默認值。 如果您的鈎子不作為參數傳遞,則不應將其存儲為參數默認值。

如果您確實希望以后能夠修改鈎子,則應使裝飾器成為一個將鈎子自身存儲的類。 這是一個例子:

class CaptainHook(object):
    def __init__(self, func):
        self.hooks = []
        self.func = func

    def __call__(self, *args, **kwargs):
        for hook in self.hooks:
            hook(*args, **kwargs)
        return self.func(*args, **kwargs)

然后:

>>> @CaptainHook
... def sum(a, b):
...     return a+b
>>> sum(1, 2)
3
>>> def aHook(*args, **kwargs):
...     print "I am a hook!"
>>> sum.hooks.append(aHook)
>>> sum(1, 2)
I am a hook!
3

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM