2010-01-31 18 views
8

Die folgende aus irgendeinem Grund nicht funktioniert:Gibt es eine Möglichkeit, eine Klasseneigenschaft in Python zu erstellen?

>>> class foo(object): 
...  @property 
...  @classmethod 
...  def bar(cls): 
...    return "asdf" 
... 
>>> foo.bar 
<property object at 0x1da8d0> 
>>> foo.bar + '\n' 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: unsupported operand type(s) for +: 'property' and 'str' 

Gibt es eine Möglichkeit, dies zu tun, oder ist meine einzige Alternative zu einer Art metaclass Tricks zu greifen?

+1

Für jeden, der mit "Eigenschaften" in Python nicht vertraut ist, wird Ihnen das vielleicht helfen, zu verstehen, worüber Jason spricht http://docs.python.org/library/functions.html#property – MatrixFrog

Antwort

6

Wenn der Deskriptor property ausgelöst werden soll, wenn Sie ein Attribut von Objekt X erhalten, müssen Sie den Deskriptor in type(X) setzen. Also, wenn X eine Klasse ist, muss der Deskriptor in den Klassen-Typ gehen, auch bekannt als die Metaklasse der Klasse - keine "Trickie" beteiligt, es ist nur eine Frage von ganz allgemeinen Regeln.

Alternativ können Sie Ihren eigenen speziellen Deskriptor schreiben. Siehe here für ein ausgezeichnetes "How-To" -Vertrag über Deskriptoren. bearbeiten zum Beispiel:

class classprop(object): 
    def __init__(self, f): 
    self.f = classmethod(f) 
    def __get__(self, *a): 
    return self.f.__get__(*a)() 

class buh(object): 
    @classprop 
    def bah(cls): return 23 

print buh.bah 

23 emittiert, wie gewünscht.

+0

Ich benutze eine Metaklasse woanders in der Vererbungshierarchie, also wenn ich die Metaklasse verwende, bekomme ich folgendes: 'Metaklassenkonflikt: Die Metaklasse einer abgeleiteten Klasse muss eine (nicht-strikte) Unterklasse der Metaklassen aller ihrer Basen sein. –

+0

* Allerdings *, der Dekorator hat funktioniert wie ein Zauber. Vielen Dank! –

+0

@Jason, Sie könnten auch eine Unterklasse aller beteiligten Metaklassen verwenden, wie die Fehlermeldung sagt (wenige verwenden mehrere benutzerdefinierte Metaklassen oder Metaklassen, die nicht vom Typ "Typ" abstammen), also müssen Sie wahrscheinlich nur die eine benutzerdefinierte Metaklasse ableiten Verwenden Sie) - aber wenn der benutzerdefinierte Deskriptor den Job erledigt, kann es in der Tat ein einfacherer Ansatz sein. –

Verwandte Themen