当前位置:  开发笔记 > 编程语言 > 正文

Python中的Decorator类

如何解决《Python中的Decorator类》经验,为你挑选了3个好方法。

我想构造用作装饰器的类,原则如下:

    应该可以在top off 1函数上堆叠多个这样的类装饰器.

    生成的函数名称指针应该与没有装饰器的同一函数无法区分,可以保存它的类型/类.

    除非装饰者实际要求,否则对装饰器进行排序不应该是相关的.IE浏览器.独立装饰者可以按任何顺序应用.

这是一个Django项目,我正在处理的具体情况现在该方法需要2个装饰器,并显示为普通的python函数:

@AccessCheck
@AutoTemplate
def view(request, item_id) {}

@AutoTemplate更改了函数,以便它不返回HttpResponse,而只返回一个字典以供在上下文中使用.使用RequestContext,并从方法名称和模块推断模板名称.

@AccessCheck根据item_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));

此外,尝试添加"打印FUNC.名称在NullDecl构造函数,它会为第一个装饰工作,而不是第二个" -正如名字将会丢失.

精致的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

eduffy.. 23

一个do-nothing装饰器类看起来像这样:

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

也许还有一个地方可以将`**kwargs`添加到定义`def __call__(self,*args):`(以及稍后调用`self.func`)? (7认同)


f3lix.. 10

该装饰模块可以帮助你编写签名保留装饰.

而PythonDecoratorLibrary可能会为装修提供有用的例子.



1> eduffy..:

一个do-nothing装饰器类看起来像这样:

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


也许还有一个地方可以将`**kwargs`添加到定义`def __call__(self,*args):`(以及稍后调用`self.func`)?

2> f3lix..:

该装饰模块可以帮助你编写签名保留装饰.

而PythonDecoratorLibrary可能会为装修提供有用的例子.



3> codeape..:

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

例:

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


如果你想使用类,我不知道你把@ functools.wraps放在哪里.我觉得作为装饰器的功能更加pythonic.代码更短.
推荐阅读
小白也坚强_177
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有