2016-06-29 38 views
0

我有一个类,我想在类内的列表中的所有方法,即使我有两个同名的方法,我希望它工作,我的问题是我不能访问该类以将方法放在那里。 可以说我有装饰用装饰器保存所有的类方法

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不存在,但是可能有一种方法可以访问它的变量,因为装饰器在其中运行?

+0

但你*不能*有两种方法具有相同的名称。 –

+0

这个怎么样? https://ideone.com/FIa3C6 – falsetru

+0

@DanielRoseman:但你*可以*将它们添加到同一个列表中,因为它们按顺序执行。这个类只会接收最后一个,因为它确实替换了类的主体名称空间中的第一个,但这并不意味着装饰器将不会被执行,并且在替换之前您将拥有对第一个函数对象的引用第二。 –

回答

1

类对象本身只有身体报表(以下简称class <classname>(<bases,>):块内的所有语句都被执行后建造,装饰,另一方面与他们装饰功能一起执行。

你可以只是在你想添加的方法,以你的装饰清单:

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 
+0

谢谢!我使用的是Python 2.7,但仍然是相互冲突的解决方案 – kill129