Gegenwärtig überschreibe ich die Klasse ' __setattr__
() gegen Ende der' __init__
() Methode der Klasse, um die Erzeugung neuer Attribute zu verhindern -
Gibt es eine Möglichkeit, das manuelle Überschreiben von __setattr__
() zu vermeiden und dies automatisch mit Hilfe von Metaklassen zu tun?
Am nächsten kam ich -
%Vor% Gibt es einen allgemeineren Weg dies zu tun, so dass apriori Wissen der Unterklassen-Attribute nicht benötigt wird?
Wie kann man die Zeile dctry.update({'x': 0, 'y': 0})
vermeiden und unabhängig von den Namen der Klassenattribute arbeiten?
P.S. - FWIW Ich habe bereits die Optionen __slots__
und namedtuple ausgewertet und festgestellt, dass sie für meine Bedürfnisse nicht ausreichen. Bitte beschränken Sie nicht den Fokus auf das reduzierte Punkte () Beispiel, das ich verwendet habe, um die Frage zu illustrieren; Der eigentliche Anwendungsfall beinhaltet eine viel komplexere Klasse.
Wäre das für Ihren Fall sinnvoll?
%Vor%Sie müssen wahrscheinlich ein bisschen mehr damit herumspielen, um es eleganter zu machen, aber die allgemeine Idee ist, __setattr__ nur zu überschreiben, nachdem init aufgerufen wurde.
Nachdem dies gesagt wurde, besteht ein gängiger Ansatz darin, object.__setattr__(self, field, value)
intern zu verwenden, um den AttributeError zu umgehen:
Sie brauchen keine Metaklassen, um diese Art von Problem zu lösen.
Wenn Sie die Daten einmal im Voraus erstellen und dann unveränderlich haben wollen, würde ich definitiv eine namedtuple wie shx2 vorschlägt.
Andernfalls definieren Sie einfach eine Sammlung zulässiger Felder für die Klasse und haben __setattr__
check, um zu sehen, ob der Name, den Sie zu setzen versuchen, in der Sammlung zulässiger Felder enthalten ist. Sie müssen die Implementierung von __setattr__
part nicht durch __init__
ändern - es funktioniert während __init__
genau so, wie es später funktioniert. Verwenden Sie eine tuple
oder eine frozenset
als Datenstruktur für die zulässigen Felder, wenn Sie davon abraten wollen, sie in einer bestimmten Klasse zu mutieren / zu ändern.
Dies kann leicht in eine Basisklasse zur Wiederverwendung ausgegliedert werden:
%Vor% Ich glaube nicht, dass es als pythonisch gilt, die erlaubten Attribute eines Objekts auf diese Weise zu sperren, und es wird einige Komplikationen für Unterklassen verursachen, die zusätzliche Attribute benötigen (eine Unterklasse wird haben) um sicherzustellen, dass das Feld _allowed_attrs
den entsprechenden Inhalt hat).
Ich habe das gleiche Bedürfnis (für eine Entwicklungs-Quick-Hack-API). Ich verwende dafür keine Metaklassen, nur Vererbung:
%Vor%Dann:
%Vor%Wenn ich Base ableiten und zusätzliche Attribute hinzufügen muss, verwende ich unlock:
%Vor%Wenn Base abstrakt ist, können Sie das Sperren überspringen und nur die Childs sperren. Ich habe dann einige Unittests, die überprüfen, dass jede öffentliche Klasse nach init gesperrt ist, um mich zu fangen, wenn ich die Sperre vergesse.
Tags und Links python python-2.7 metaclass