使用装饰器保存所有类方法

时间:2016-06-29 11:11:59

标签: python

我有一个类,我想在类中的列表中的所有方法,我希望它工作,即使我有两个同名的方法,我的问题是我无法访问类放到方法那里。 假设我有装饰师

def dec(func):
    class = ????
    class.methods.append(func)
    return func

我有班级

class A(object):
    methods = []
    @dec
    def a(self):
       print 2
    @dec
    def a(self):
       print 3

我希望能够做到

A.methods[0](A())
A.methods[1](A())
(A() becuase those methods need self)

或类似的东西

我已经阅读了很多像这样的问题,看起来我想要的并不是真的可能,因为调用装饰器时A不存在,但也许有一种方法来访问它的变量,因为装饰器在它内部运行?

1 个答案:

答案 0 :(得分:1)

类对象本身仅在 body语句之后构造class <classname>(<bases,>):块中的所有语句都已执行。另一方面,decorators与它们的函数一起执行装饰。

您可以在列表中将希望方法添加到装饰器中:

class A(object):
    methods = []
    @dec(methods)
    def a(self):
        print 2
    @dec(methods)
    def a(self):
        print 3

让装饰者使用该列表附加你的方法:

def dec(methodslist):
    def decorator(f):
        methodslist.append(f)
        return f
    return decorator

如果您使用的是Python 3,那么另一个选项是您使用自定义metaclass.__prepare__ class method的元类,它使用collections.defaultdict()首先将所有属性收集到列表中,这样即使您仍然可以访问它们命名相同。然后你的装饰者只需要用额外的属性或其他东西“标记”每个函数对象。这有点多了。

当你想要调用这些函数时,你是对的,他们没有绑定,也不会为你传递self。手动传入self绑定。函数是descriptor objects,调用它们的__get__方法将它们绑定到实例:

for func in self.methods:
    method = func.__get__(self)
    method()

演示:

>>> def dec(methodslist):
...     def decorator(f):
...         methodslist.append(f)
...         return f
...     return decorator
...
>>> class A(object):
...     methods = []
...     @dec(methods)
...     def a(self):
...         print 2
...     @dec(methods)
...     def a(self):
...         print 3
...     def call_all(self):
...         for func in self.methods:
...             method = func.__get__(self)
...             method()
...
>>> A().call_all()
2
3