简体   繁体   English

如何在装饰器中混合* args,** kwargs和命名参数

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

I want to create a custom decorator, called captain_hook . 我想创建一个自定义的装饰器,称为captain_hook It should store hooks - functions to be called before the decorated function - and call them: 它应该存储hooks (要在修饰的函数之前调用的函数)并调用它们:

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

Now I could say: 现在我可以说:

@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

The problem is that I can't pass the arguments to closure , cause first element of args mistakingly unpacks to hooks argument: sum(1, 2) sets hook=1 , a=2 , b - undefined . 问题是我无法将参数传递给closure ,导致args第一个元素错误地解压缩到hooks参数: sum(1, 2)设置hook=1a=2b - undefined How do I do that? 我怎么做?

Modifying __defaults__ is a very dubious way to handle this. 修改__defaults__是一种处理此问题的非常可疑的方法。 __defaults__ is for argument default values. __defaults__用于参数默认值。 If your hooks aren't going to be passed as arguments, you shouldn't store them as an argument default value. 如果您的钩子不作为参数传递,则不应将其存储为参数默认值。

If you really want to be able to modify the hooks later on, you should make your decorator a class that stores the hooks on itself. 如果您确实希望以后能够修改钩子,则应使装饰器成为一个将钩子自身存储的类。 Here's an example: 这是一个例子:

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)

Then: 然后:

>>> @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