Ich habe ein Python-Objekt mit mehreren Attributen und Methoden. Ich möchte über Objektattribute iterieren.
class my_python_obj(object):
attr1='a'
attr2='b'
attr3='c'
def method1(self, etc, etc):
#Statements
Ich möchte ein Wörterbuch generieren, das alle Objektattribute und ihre aktuellen Werte enthält, aber ich möchte dies auf dynamische Weise tun (wenn ich später ein weiteres Attribut hinzufüge, muss ich nicht daran denken, auch meine Funktion zu aktualisieren).
In PHP können Variablen als Schlüssel verwendet werden, aber Objekte in Python sind nicht beschreibbar. Wenn ich hierfür die Punktnotation verwende, wird ein neues Attribut mit dem Namen meiner Variable erstellt, was nicht meine Absicht ist.
Nur um die Dinge klarer zu machen:
def to_dict(self):
'''this is what I already have'''
d={}
d["attr1"]= self.attr1
d["attr2"]= self.attr2
d["attr3"]= self.attr3
return d
· ·
def to_dict(self):
'''this is what I want to do'''
d={}
for v in my_python_obj.attributes:
d[v] = self.v
return d
Update: Mit Attributen meine ich nur die Variablen dieses Objekts, nicht die Methoden.
python
oop
attributes
iteration
Pablo Mescher
quelle
quelle
predicate
Argument verwenden, um eine aufrufbare Datei zu übergeben, die (gebundene?) Funktionen herausfiltert (wodurch die Methoden entfernt werden).Antworten:
Angenommen, Sie haben eine Klasse wie
Wenn Sie
dir
das Objekt aufrufen, erhalten Sie alle Attribute dieses Objekts zurück, einschließlich der speziellen Python-Attribute. Obwohl einige Objektattribute aufrufbar sind, wie z. B. Methoden.Sie können die speziellen Methoden jederzeit mithilfe eines Listenverständnisses herausfiltern.
oder wenn Sie Karte / Filter bevorzugen.
Wenn Sie die Methoden herausfiltern möchten, können Sie die integrierte Methode
callable
als Prüfung verwenden.Sie können auch den Unterschied zwischen Ihrer Klasse und ihrem Instanzobjekt mithilfe von untersuchen.
quelle
callable
oder beinhaltentypes.MethodType
. Was passiert, wenn ich ein Attribut namens "_foo" hinzufüge, in dem ein Zwischenergebnis oder eine interne Datenstruktur gespeichert ist? Was passiert, wenn ich der Klasse harmlos ein Attribut hinzufügename
, z. B., und jetzt plötzlich wird es aufgenommen?_foo
undname
weil sie jetzt Attribute des Objekts sind. Wenn Sie sie nicht einschließen möchten, können Sie sie in der Listenverständnisbedingung ausschließen. Der obige Code ist eine gängige Python-Redewendung und eine beliebte Methode zur Überprüfung von Python-Objekten.dir()
"lügt" nur, wenn Metaklassen (ein Fall mit extremen Kanten) oder Klassen mit Attributen übergeben werden, die durch@DynamicClassAttribute
(ein weiterer Fall mit extremen Kanten) gekennzeichnet sind. In beiden Fällen wird dies durch Aufrufen desdirs()
Wrappersinspect.getmembers()
behoben. Für Standardobjekte reicht jedoch der Listenverständnisansatz dieser Lösung zum Herausfiltern nicht aufrufbarer Elemente absolut aus. Dass einige Pythonisten es als "schlechte Idee" bezeichnen würden, verblüfft mich, aber ... für jeden seine eigene, nehme ich an?Fügen Sie im Allgemeinen eine
__iter__
Methode in Ihre Klasse ein und durchlaufen Sie die Objektattribute oder fügen Sie diese Mixin-Klasse in Ihre Klasse ein.Deine Klasse:
quelle
one
und danachtwo
definiert wirdyc = YourClass()
. Die Frage fragt nach dem Durchlaufen des vorhandenen Attris inYourClass()
. Außerdem ist das Erben derIterMixin
Klasse möglicherweise nicht immer als Lösung verfügbar.vars(yc)
gibt das gleiche Ergebnis, ohne von einer anderen Klasse erben zu müssen.vars(yc)
ist fast dasselbe, aber das Wörterbuch, das es Ihnen zurückgibt, gehört der Instanz.__dict__
Wenn Sie es ändern, wird es in der Instanz wiedergegeben. Dies kann zu Problemen führen, wenn Sie nicht vorsichtig sind. Daher ist die oben beschriebene Methode manchmal besser (obwohl das Kopieren des Wörterbuchs wahrscheinlich einfacher ist). Beachten Sie außerdem, dass das oben zurückgegebene Wörterbuch zwar nicht das der Instanz ist__dict__
, die Werte jedoch dieselben sind, sodass das Ändern von veränderlichen Werten weiterhin in den Attributen der Instanz berücksichtigt wird.Wie bereits in einigen Antworten / Kommentaren erwähnt, speichern Python-Objekte bereits ein Wörterbuch ihrer Attribute (Methoden sind nicht enthalten). Auf diese kann zugegriffen werden
__dict__
, aber der bessere Weg ist die Verwendungvars
(die Ausgabe ist jedoch dieselbe). Beachten Sie, dass durch Ändern dieses Wörterbuchs die Attribute der Instanz geändert werden! Dies kann nützlich sein, bedeutet aber auch, dass Sie bei der Verwendung dieses Wörterbuchs vorsichtig sein sollten. Hier ist ein kurzes Beispiel:Die Verwendung
dir(a)
ist eine seltsame, wenn nicht geradezu schlechte Herangehensweise an dieses Problem. Es ist gut, wenn Sie wirklich alle Attribute und Methoden der Klasse durchlaufen müssen (einschließlich der speziellen Methoden wie__init__
). Dies scheint jedoch nicht das zu sein, was Sie wollen, und selbst die akzeptierte Antwort geht schlecht dahin, indem Sie eine spröde Filterung anwenden, um zu versuchen, Methoden zu entfernen und nur die Attribute zu belassen. Sie können sehen, wie dies für die Klasse fehlschlagen würdeA
oben definierte .(Die Verwendung
__dict__
wurde in einigen Antworten durchgeführt, aber alle definieren unnötige Methoden, anstatt sie direkt zu verwenden. Nur ein Kommentar schlägt die Verwendung vor.vars
)quelle
a.b
als eine benutzerdefinierte KlasseB
dannvars(a)["b"] is a.b
, wie man erwarten würde; nichts anderes würde wirklich Sinn machen (denken Sie ana.b
syntaktischen Zucker füra.__dict__["b"]
). Wenn Sie habend = vars(a)
und aufrufenrepr(d)
, wird esrepr(d["b"])
als Teil der Rückgabe seiner eigenen Repr-Zeichenfolge aufgerufen, da nur die KlasseB
wirklich weiß, wie es als Zeichenfolge dargestellt werden soll.Objekte in Python speichern ihre Attribute (einschließlich Funktionen) in einem Diktat namens
__dict__
. Sie können (sollten dies aber im Allgemeinen nicht) verwenden, um direkt auf die Attribute zuzugreifen. Wenn Sie nur eine Liste möchten, können Sie auch anrufendir(obj)
, die eine Iterable mit allen Attributnamen zurückgibt, an die Sie dann übergeben könnengetattr
.Es ist jedoch normalerweise ein schlechtes Design, irgendetwas mit den Namen der Variablen tun zu müssen. Warum sie nicht in einer Sammlung aufbewahren?
Sie können dann mit über die Tasten iterieren
for key in obj.special_values:
quelle
dann nenne es einfach als iterable
quelle
Die richtige Antwort darauf ist, dass Sie nicht sollten. Wenn Sie diese Art von Dingen möchten, verwenden Sie entweder nur ein Diktat oder Sie müssen einem Container explizit Attribute hinzufügen. Sie können dies automatisieren, indem Sie sich mit Dekorateuren vertraut machen.
Insbesondere Methode1 in Ihrem Beispiel ist übrigens genauso gut für ein Attribut.
quelle
Für Python 3.6
quelle
Für alle pythonischen Eiferer da draußen bin ich sicher, dass Johan Cleeze Ihren Dogmatismus gutheißen würde;). Ich lasse diese Antwort immer wieder herabsetzen. Das macht mich selbstbewusster. Hinterlasse einen Kommentar du Hühner!
Für Python 3.6
quelle