Ich habe eine Python-Klasse, die so aussieht:
class Process:
def __init__(self, PID, PPID, cmd, FDs, reachable, user):
gefolgt von:
self.PID=PID
self.PPID=PPID
self.cmd=cmd
...
Gibt es eine Möglichkeit, diese Instanzvariablen wie die Initialisierungsliste von C ++ automatisch zu initialisieren? Es würde viel redundanten Code sparen.
python
class
initialization-list
Adam Matan
quelle
quelle
autoassign
Activestate-Rezepts und eine alternativeautoargs
Implementierung unter: Was ist der beste Weg, um eine automatische Attributzuweisung in PythonAntworten:
Sie können einen Dekorateur verwenden:
Verwenden Sie es, um die
__init__
Methode zu dekorieren :Ausgabe:
quelle
Wenn Sie Python 2.6 oder höher verwenden, können Sie collection.namedtuple verwenden :
Dies ist besonders dann angebracht, wenn Ihre Klasse wirklich nur eine große Tüte mit Werten ist.
quelle
Für Python 3.7+ können Sie verwenden Datenklasse , die ein sehr pythonic und wartbar Weg ist , zu tun , was Sie wollen.
Hier können Sie Felder für Ihre Klasse definieren, die Ihre automatisch initialisierten Instanzvariablen sind.
Es würde ungefähr so aussehen:
Die
__init__
Methode wird bereits in Ihrer Klasse sein.Beachten Sie, dass hier Typhinweise erforderlich sind, deshalb habe ich
int
undstr
im Beispiel verwendet. Wenn Sie den Typ Ihres Feldes nicht kennen, können Sie Beliebig aus demtyping
Modul verwenden .Die Datenklasse hat gegenüber den vorgeschlagenen Lösungen viele Vorteile:
**kwargs
.__init__
Mit dieser__post_init__
Methode können Sie über die automatische Methode hinausgehen .BEARBEITEN: Gründe, die Verwendung von NamedTuples zu vermeiden
Einige schlagen die Verwendung von
namedtuple
für diesen Fall vor, aber Namedtuples weisen einige Verhaltensweisen auf, die sich von Python-Klassen unterscheiden, die zunächst nicht wirklich offensichtlich sind und bekannt sein sollten:1. NamedTuples sind unveränderlich
Unveränderlichkeit kann nützlich sein, aber vielleicht ist es nicht das, was Sie für Ihre Instanzen wollen. DataClasses können auch irgendwie unveränderlich sein, wenn Sie das Argument
frozen=True
für den@dataclass
Dekorator verwenden.2. NamedTuples
__eq__
verhält sich wie TuplesIn Python
SomeNamedTuple(a=1, b=2) == AnotherNamedTuple(c=1, d=2)
istTrue
! Die__eq__
in Vergleichen verwendete Funktion NamedTuple berücksichtigt nur die Werte und Positionen dieser Werte in den verglichenen Instanzen, nicht die Namen ihrer Klassen oder Felder.quelle
Data Classes can be thought of as "mutable namedtuples with defaults".
- PEP557Zitiert das Zen von Python ,
quelle
Eine andere Sache, die Sie tun können:
Aber die einzige Lösung, die ich empfehlen würde, ist "Makro in Ihrem Editor erstellen" ;-p
quelle
Sie können dies problemlos mit den Schlüsselwortargumenten tun, z. B.:
Eine ähnliche Implementierung für die Positionsargumente wäre:
was mir Ihr Problem nicht zu lösen scheint.
quelle
self.__dict__.update( **kwargs )
Nadias Lösung ist besser und leistungsfähiger, aber ich finde das auch interessant:
quelle
Ich brauchte etwas für den gleichen Zweck, aber keine der vorhandenen Antworten deckte alle von mir getesteten Fälle ab. Nadias Antwort kam meiner Suche am nächsten, also begann ich mit ihrem Code als Basis.
Der folgende Dekorateur arbeitet mit allen gültigen Kombinationen von Argumenten:
Außerdem wird die Standardkonvention
_
-prefix implementiert , um__init__
-private Variablen zuzulassen, die Klasseninstanzen nicht zugewiesen werden.Hinweis:
Ich habe Tests eingeschlossen, sie aber der Kürze halber in der letzten Zeile ( 58 ) zusammengefasst. Sie können die Tests, in denen alle potenziellen Anwendungsfälle aufgeführt sind, erweitern, indem Sie
find/replace
alle$
Zeichen mit einer neuen Zeile versehen.quelle
Möglicherweise müssen keine Variablen initialisiert werden, da local () die Werte bereits enthält!
Klasse Dummy (Objekt):
d = Dummy (2, 3)
d.params
{'a': 2, 'b': 3, 'default': 'Fred'}
d.params ['b']
3
Natürlich kann man innerhalb einer Klasse self.params verwenden
quelle
d['b']
ist in Python geschrieben lingua franca , währendd.params['b']
wird Verwirrung für die Code - Leser verursachen.Sobald
getargspec
es seit Python 3.5 veraltet ist, ist hier die Lösung mitinspect.signature
:Überprüfen Sie, ob es funktioniert:
quelle
Für Python 3.3+:
Demo:
Ein Nicht-Dekorator-Ansatz für Python 2 und 3 unter Verwendung von Frames:
Demo:
quelle
nu11ptr hat mit PyInstanceVars ein kleines Modul erstellt , das diese Funktionalität als Funktionsdekorateur enthält. In der README des Moduls heißt es, dass die [...] Leistung jetzt nur noch 30-40% schlechter ist als die explizite Initialisierung unter CPython .
Anwendungsbeispiel, direkt aus der Dokumentation des Moduls entnommen :
quelle
Vielleicht ist dies eine geschlossene Frage, aber ich möchte meine Lösung vorschlagen, um zu wissen, was Sie darüber denken. Ich habe eine Metaklasse verwendet, die einen Dekorator auf die Init- Methode anwendet
quelle
Die attrs- Bibliothek macht so etwas.
quelle
am Ende der Init- Funktion:
Weitere
setattr()
Informationen finden Sie hierquelle