【问题标题】:Pass current class to decorator function将当前类传递给装饰器函数
【发布时间】:2014-01-07 14:36:05
【问题描述】:

我有一个装饰器方法来检查传递给函数的参数类型。

def accepts(*types):
    def check_accepts(f):
        assert len(types) == f.func_code.co_argcount
        def new_f(*args, **kwds):
            for (a, t) in zip(args, types):
                assert isinstance(a, t), \
                       "arg %r does not match %s" % (a,t)
            return f(*args, **kwds)
        new_f.func_name = f.func_name
        return new_f
    return check_accepts

现在,在一个类中(classA.py),我想要一个只接受同一个类的参数的方法:

class ClassA:
    @accepts(WHATTOPUTHERE)
    def doSomething(otherObject):
        # Do something

在其他类中,我可以将ClassA 代替WHATTOPUTHERE,但在classA.py 中,ClassA 是未知的。如何将当前类传递给@accepts() 函数?

【问题讨论】:

  • 对不起,我不知道你的意思。那不是我的意图,不。你能解释一下为什么会这样吗?
  • 嗯,想想,这里不会发生的;您已经重新实现了与 Python 2 中已经方法相同的类型检查;强制self 为同一类型或当前类的子类。但似乎你没有考虑到args[0] 在这里是self

标签: python types decorator typechecking python-decorators


【解决方案1】:

使用基于函数的装饰器版本并在类定义之后应用它:

class ClassA:
    def doSomething(otherObject):
        # Do something
ClassA.doSomething = accepts(ClassA)(ClassA.doSomething)

另一种方法是编写一个Metaclass,它会在创建类后自动应用它:

class Meta(type):

    def __new__(cls, clsname, bases, dct):
       fields = ('doSomething', ) #Fields on which you want to apply the decorator
       for name, val in dct.items():
           if name in fields:
               dct[name] = accepts(cls)(val)
       return type.__new__(cls, clsname, bases, dct)


class ClassA(object):
    __metaclass__ = Meta
    def doSomething(otherObject):
        pass

不要手动执行new_f.func_name = f.func_name 之类的操作,而是使用functools.wraps。这也将保留文档字符串、参数列表等内容。

from functools import wraps
def accepts(*types):
    def check_accepts(f):
        print "inside"
        assert len(types) == f.func_code.co_argcount
        @wraps(f)
        def new_f(*args, **kwds):

【讨论】:

    【解决方案2】:

    不会将self 变量添加到函数doSomething,然后在check_accepts 中引用args[0](前提是您在定义中添加(*args) 或额外参数)解决您的问题?如果函数doSomething 应该是一个类方法,你仍然可以外包这个self。怎么样?

    • self 添加到类中的某个虚拟方法中
    • 制作一个装饰器,用于填充accepts 可以通过某种方式访问​​的变量(如元数据)
    • 确保在doSomething() 之前调用此附加方法
    • 您已经获得了类实例!享受!

    注意:这不是像这样存储元数据并在以后使用它的唯一方法,您可以按照自己的意愿进行操作。

    【讨论】:

      猜你喜欢
      • 2021-11-15
      • 2021-11-21
      • 2018-08-24
      • 1970-01-01
      • 2019-01-25
      • 2016-01-30
      • 1970-01-01
      • 2016-02-14
      • 2014-11-17
      相关资源
      最近更新 更多