2016-06-29 5 views
0

Ich habe eine Klasse und ich möchte alle Methoden in einer Liste innerhalb der Klasse, ich will es funktioniert, auch wenn ich zwei Methoden mit dem gleichen Namen haben, mein Problem ist, kann ich nicht Greife auf die Klasse zu, um die Methoden dort zu platzieren. kann sagen, ich habe den DekorateurSpeichern Sie alle Klassenmethoden mit Decorator

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

und ich habe die Klasse

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

ich will

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

oder etwas tun können, wie die

ich schon lese viele Probleme wie diese und es sieht so aus, als ob was ich will, ist nicht wirklich möglich, da A ist nicht vorhanden, wenn der Dekorator aufgerufen wird, aber vielleicht gibt es eine Möglichkeit, auf seine Variablen zuzugreifen, da der Dekorator darin läuft?

+0

Aber Sie * nicht * haben zwei Methoden mit dem gleichen Namen. –

+0

Wie wäre es damit? https://ideone.com/FIa3C6 – falsetru

+0

@DanielRoseman: aber Sie * können * sie zur gleichen Liste hinzufügen, wie sie in der Reihenfolge ausgeführt werden. Die Klasse erhält nur die letzte, da sie tatsächlich die erste im Namensraum des Klassenkörpers ersetzt, aber das bedeutet nicht, dass der Dekorator nicht ausgeführt wird und Sie einen Verweis auf das erste Funktionsobjekt haben, bevor es ersetzt wird durch die Sekunde. –

Antwort

1

Das Klassenobjekt selbst wird nur nach der Körper Aussagen (alle Aussagen innerhalb des class <classname>(<bases,>): Block ausgeführt wurden konstruiert. Zierer auf der anderen Seite ausgeführt werden zusammen mit der Funktion, die sie schmücken.

Sie könnten nur in der Liste Sie Methoden hinzugefügt werden möchten, zu Ihrem Dekorateur:

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

und haben den Dekorateur, die Ihre Methoden anhängen Liste:

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

Wenn Sie Python 3 verwenden, verwenden Sie eine Metaklasse mit einer benutzerdefinierten metaclass.__prepare__ class method, die collections.defaultdict() verwendet, um alle Attribute zuerst in Listen zu sammeln, damit Sie auch dann auf sie zugreifen können, wenn sie gleich benannt sind. Ihr Dekorator muss dann nur jedes Funktionsobjekt mit einem zusätzlichen Attribut oder etwas "markieren". Dies ist ein wenig mehr beteiligt.

Wenn Sie dann diese Funktionen aufrufen möchten, haben Sie recht, dass sie nicht gebunden sind und self nicht für Sie übergeben werden. Geben Sie entweder self oder manuell manuell ein. Funktionen sind descriptor objects, rufen ihre __get__ Methode, um sie zu einer Instanz zu binden:

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

Demo:

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

danke! Ich benutze Python 2.7, aber immer noch interessante Lösungen – kill129

Verwandte Themen