Python __getattribute__ override und @ property decorator

Ich musste eine Klasse schreiben, die __getattribute__ überschreibt. Grundsätzlich ist meine Klasse ein Container, der jede benutzerdefinierte Eigenschaft auf self._meta was ein Wörterbuch ist.

 class Container(object): def __init__(self, **kwargs): super(Container, self).__setattr__('_meta', OrderedDict()) #self._meta = OrderedDict() super(Container, self).__setattr__('_hasattr', lambda key : key in self._meta) for attr, value in kwargs.iteritems(): self._meta[attr] = value def __getattribute__(self, key): try: return super(Container, self).__getattribute__(key) except: if key in self._meta : return self._meta[key] else: raise AttributeError, key def __setattr__(self, key, value): self._meta[key] = value #usage: >>> a = Container() >>> a <__main__.Container object at 0x0000000002B2DA58> >>> a.abc = 1 #set an attribute >>> a._meta OrderedDict([('abc', 1)]) #attribute is in ._meta dictionary 

Ich habe einige Klassen, die Container Basisklasse erben und einige ihrer Methoden haben @property Dekorateur.

 class Response(Container): @property def rawtext(self): if self._hasattr("value") and self.value is not None: _raw = self.__repr__() _raw += "|%s" %(self.value.encode("utf-8")) return _raw 

Problem ist, dass .rawtext nicht zugänglich ist. (Ich bekomme attributeerror.) Jeder Schlüssel in ._meta ist zugänglich, alle Attribute, die von __setattr__ der object hinzugefügt werden, sind zugänglich, aber Methoden-zu-Eigenschaften von @property Dekorator ist nicht. Ich denke, es hat mit meinem Weg zu überschreiben __getattribute__ in Container Basisklasse zu tun. Was soll ich tun, um Eigenschaften von @property zugänglich zu machen?

  • Inspektion von Pythonenklassenattributen
  • Klassenattribute, die nicht an Objekte übergeben werden
  • Korrekte Weise, Klassenvariablen in Python zu definieren
  • Pythonenklassenattribut
  • Dynamische Instanzattribute
  • Python-Klasse-Attribute und deren Initialisierung
  • Python. Merkwürdige Klassenattribute Verhalten
  • Im Klassenobjekt, wie man Auto-Attribute automatisch aktualisiert?
  • 2 Solutions collect form web for “Python __getattribute__ override und @ property decorator”

    Ich denke, du solltest wohl daran denken, __getattr__ anstelle von __getattribute__ hier zu betrachten. Der Unterschied ist das: __getattribute__ heißt bedingungslos, wenn es existiert – __getattr__ wird nur aufgerufen, wenn python das Attribut nicht über andere Mittel finden kann.

    Ich bin mit mgilson völlig einverstanden. Wenn Sie einen Beispielcode wünschen, der Ihrem Code entsprechen sollte, aber gut mit Eigenschaften arbeiten, können Sie versuchen:

     class Container(object): def __init__(self, **kwargs): self._meta = OrderedDict() #self._hasattr = lambda key: key in self._meta #??? for attr, value in kwargs.iteritems(): self._meta[attr] = value def __getattr__(self, key): try: return self._meta[key] except KeyError: raise AttributeError(key) def __setattr__(self, key, value): if key in ('_meta', '_hasattr'): super(Container, self).__setattr__(key, value) else: self._meta[key] = value 

    Ich verstehe wirklich nicht dein _hasattr Attribut. Sie setzen es als Attribut, aber es ist eigentlich eine Funktion, die Zugriff auf sich self … sollte es nicht eine Methode sein? Eigentlich denke ich, du solltest einfach die eingebaute Funktion hasattr :

     class Response(Container): @property def rawtext(self): if hasattr(self, 'value') and self.value is not None: _raw = self.__repr__() _raw += "|%s" %(self.value.encode("utf-8")) return _raw 

    Beachten Sie, dass hasattr(container, attr) True auch für _meta .

    Eine andere Sache, die mich OrderedDict , ist, warum Sie ein OrderedDict . Ich meine, Sie iterieren über kwargs , und die Iteration hat zufällige Reihenfolge, da es eine normale dict , und fügen Sie die Elemente in der OrderedDict . Jetzt hast du _meta die die Werte in zufälliger Reihenfolge enthält. Wenn Sie nicht sicher sind, ob Sie eine bestimmte Bestellung haben oder nicht, verwenden Sie einfach dict und schließlich tauschen Sie zu OrderedDict später.

    Übrigens: Niemals einen try: ... except: ohne die Ausnahme zu fangen. In deinem Code musstest du eigentlich nur AttributeError s fangen, also hättest du tun sollen:

     try: return super(Container, self).__getattribute__(key) except AttributeError: #stuff 
    Python ist die beste Programmiersprache der Welt.