Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/batch-file/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python中的装饰器类_Python_Decorator - Fatal编程技术网

Python中的装饰器类

Python中的装饰器类,python,decorator,Python,Decorator,我希望构造类作为装饰器使用,并保持以下原则不变: 应该可以在一个函数的顶部堆叠多个这样的类装饰器 生成的函数名指针应该与没有修饰符的同一个函数不可区分,除了它是哪种类型/类 除非装饰师实际授权,否则订购装饰师不应相关。独立的装饰师可以按任何顺序使用 这是针对Django项目的,我现在正在处理的具体案例需要2个decorator,并显示为一个普通python函数: @AccessCheck @AutoTemplate def view(request, item_id) {} @AutoTemp

我希望构造类作为装饰器使用,并保持以下原则不变:

  • 应该可以在一个函数的顶部堆叠多个这样的类装饰器
  • 生成的函数名指针应该与没有修饰符的同一个函数不可区分,除了它是哪种类型/类
  • 除非装饰师实际授权,否则订购装饰师不应相关。独立的装饰师可以按任何顺序使用
  • 这是针对Django项目的,我现在正在处理的具体案例需要2个decorator,并显示为一个普通python函数:

    @AccessCheck
    @AutoTemplate
    def view(request, item_id) {}
    
    @AutoTemplate更改了函数,因此它不返回HttpResponse,而只返回一个字典,以便在上下文中使用。使用RequestContext,并根据方法名和模块推断模板名

    @AccessCheck根据项目id添加对用户的附加检查

    我猜这只是为了得到正确的构造函数并复制适当的属性,但是这些属性是什么呢

    以下装饰器将无法按照我的描述工作:

    class NullDecl (object):
        def __init__ (self, func):
            self.func = func
        def __call__ (self, * args):
            return self.func (*args)
    
    如以下代码所示:

    @NullDecl
    @NullDecl
    def decorated():
        pass
    
    def pure():
        pass
    
    # results in set(['func_closure', 'func_dict', '__get__', 'func_name',
    # 'func_defaults', '__name__', 'func_code', 'func_doc', 'func_globals'])
    print set(dir(pure)) - set(dir(decorated));
    
    另外,尝试在NullDecl构造函数中添加“print func.name”,它将适用于第一个decorator,但不会缺少第二个-as名称

    对eduffy的回答进行了一点精炼,似乎效果很好:

    class NullDecl (object):
        def __init__ (self, func):
            self.func = func
            for n in set(dir(func)) - set(dir(self)):
                setattr(self, n, getattr(func, n))
    
        def __call__ (self, * args):
            return self.func (*args)
        def __repr__(self):
            return self.func
    

    不做任何事的装饰器类如下所示:

    class NullDecl (object):
       def __init__ (self, func):
          self.func = func
          for name in set(dir(func)) - set(dir(self)):
            setattr(self, name, getattr(func, name))
    
       def __call__ (self, *args):
          return self.func (*args)
    
    然后您可以正常应用它:

    @NullDecl
    def myFunc (x,y,z):
       return (x+y)/z
    
    帮助您编写保留签名的装饰器


    并且可能会为修饰符提供有用的示例。

    要创建一个修饰符来包装函数,使其与原始函数无法区分,请使用
    functools.wrapps

    例如:

    
    def mydecorator(func):
        @functools.wraps(func):
        def _mydecorator(*args, **kwargs):
            do_something()
            try:
                return func(*args, **kwargs)
            finally:
                clean_up()
        return _mydecorator
    
    # ... and with parameters
    def mydecorator(param1, param2):
        def _mydecorator(func):
            @functools.wraps(func)
            def __mydecorator(*args, **kwargs):
                do_something(param1, param2)
                try:
                    return func(*args, **kwargs)
                finally:
                    clean_up()
            return __mydecorator
        return _mydecorator
    
    (我个人的偏好是使用函数而不是类创建装饰器)

    装饰师的顺序如下:

    
    @d1
    @d2
    def func():
        pass
    
    # is equivalent to
    def func():
        pass
    
    func = d1(d2(func))
    

    +1因为我不知道为什么有人否决了这个问题。这是一个很好的问题:大多数的decorator问题,所以不要使用类作为decorator。不管你怎么想,使用类而不是函数,这都是一个有效的问题,可能完全适合这个用例。我想我读到有人建议为装饰师使用类,但我想这是个糟糕的建议。如果你想使用类,我不知道你把@functools.wrapps放在哪里了。我觉得作为装饰者的功能更像蟒蛇。代码更短。在您的参数示例中,“func”来自哪里?它不在mydecorator()的参数列表中……您应用@decorator(param1,param2)def func:pass-decorator(param1,param2)返回将用于装饰的实际函数。这里有3个级别的嵌套函数。我添加了自己的修复程序,因此它可以正常工作。感谢您的帮助,通常有助于开始非常基本的操作。也许还有一个地方可以将
    **kwargs
    添加到定义
    def\uu调用(self,*args):
    (以及以后调用
    self.func
    )中?如何使用functool.wrapps?