Kann nicht festgelegt werden, das Attribut für die Unterklassen der namedtuple
Sieht es aus wie diese oder diese etwas Verwandte threads, aber immer noch nicht kapiert Dinge aus 🙂
Ich versuche, erstellen Sie eine Unterklasse von namedtuple
und bieten verschiedene Initialisierungen, so dass ich konstruieren von Objekten auf unterschiedliche Weise. Zum Beispiel:
>>> from collections import namedtuple
>>> class C(namedtuple("C", "x, y")) :
... __slots__ = ()
... def __init__(self, obj) : # Initialize a C instance by copying values from obj
... self.x = obj.a
... self.y = obj.b
... def __init__(self, x, y) : # Initialize a C instance from the parameters
... self.x = x
... self.y = y
Jedoch, dass nicht funktioniert:
>>> c = C(1, 2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 7, in __init__
AttributeError: can't set attribute
Nach einigen stochern (siehe beispielsweise diese thread) habe ich versucht zu verwenden Konstruktoren statt Initialisierungen:
>>> from collections import namedtuple
>>> class C(namedtuple("C", "x, y")) :
... __slots__ = ()
... def __new__(cls, obj) :
... self = super(C, cls).__new__(cls, obj.a, obj.b)
... def __new__(cls, x, y) :
... self = super(C, cls).__new__(cls, x, y)
schien zu konstruieren ein Objekt, aber dann kann ich nicht Lesen der Attribute:
>>> c = C(1,2)
>>> c.x, c.y
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'x'
Wo bin ich denn hier falsch? Wie kann ich erstellen Sie eine Unterklasse mit mehreren Konstruktoren oder Initialisierungen?
Warum haben Sie Doppelzimmer
Keine überlastung... das bedeutet Also, dass mein ursprüngliches Ziel der Schaffung von Instanzen von C auf verschiedenen wegen (je nach überladenen Konstruktoren) ist eigentlich nicht machbar?
Es ist vollkommen machbar, nur mit unterschiedlichen Paradigmen.
Siehe mein Kommentar weiter unten, unter deiner Antwort. Sie sagen, es ist machbar mit factory-Methoden, aber nicht mit mehreren "Konstruktoren"?
Sie können die Verwendung von nur einem Konstruktor, aber der Konstruktor kann variieren Verhalten auf der Grundlage der Argumente, die Sie übergeben.
__init__
und __new__
Methoden? Nur die Sekunde zählt, überschreibt er den ersten. Python macht nicht 'überladen' Methoden Signaturen.Keine überlastung... das bedeutet Also, dass mein ursprüngliches Ziel der Schaffung von Instanzen von C auf verschiedenen wegen (je nach überladenen Konstruktoren) ist eigentlich nicht machbar?
Es ist vollkommen machbar, nur mit unterschiedlichen Paradigmen.
Siehe mein Kommentar weiter unten, unter deiner Antwort. Sie sagen, es ist machbar mit factory-Methoden, aber nicht mit mehreren "Konstruktoren"?
Sie können die Verwendung von nur einem Konstruktor, aber der Konstruktor kann variieren Verhalten auf der Grundlage der Argumente, die Sie übergeben.
InformationsquelleAutor Jens | 2013-10-08
Du musst angemeldet sein, um einen Kommentar abzugeben.
Benannten Tupel unveränderlich sind, so kann man nicht manipulieren, Sie in die
__init__
Initialisierung. Ihre einzige option ist das überschreiben der__new__
Methode:Beachten Sie, dass, weil
__new__
ist eine factory-Methode für neue Instanzen, die Sie brauchen, um zurück die neu erstellte Instanz. Wenn Sie nicht verwendenreturn
im__new__
Methode, der default-Rückgabewert istNone
, die Ihnen Ihre Fehler.Demo mit einem Objekt mit
x
undy
Attribute:Python unterstützt kein überladen von Methoden; im Allgemeinen werden Sie entweder mit den optionalen Schlüsselwort-Argumente oder extra-Klasse Methoden als factory-Methoden.
Den
datetime
- Modul, zum Beispiel, hat mehrere solcher factory-Methoden, damit Sie Objekte erstellen, die nicht mit den standard-Konstruktor.datetime.datetime.fromtimestamp()
schafft einedatetime.datetime
Instanz aus einer einzigen numerischen Wert, und so hatdatetime.datetime.fromordinal()
; außer, Sie interpretieren Sie die Zahl in unterschiedlicher Weise.Wenn Sie wollte, variable Argumente unterstützen, tun:
Hier
y
ist ein optionales argument, säumigeNone
wenn nicht vom Aufrufer bereitgestellte:Die alternative, über eine Klasse, Methode, der wäre:
Nun gibt es zwei factory-Methoden; eine Standard-und eine mit dem Namen:
x
undy
) und eine zweite Fabrik-Methode (die erhält eineobj
). Nicht schön, vielleicht sollte ich lieber den C++ - Stil-Konstruktor überladen, aber ich denke, das ist so viel wie ich kann mit Python.Was ist mit der _replace-Methode? docs.python.org/2/library/...
was ist mit es? Können Sie das noch näher erläutern? Beachten Sie, dass
instance._replace()
gibt eine neue Instanz, das original bleibt unverändert.._replace()
wird nicht machen Sie eine factory-Funktion effizienter.Wahr. Sie können dies tun:
c = c._replace(x=30)
. Ich glaube, es ist besser, auf vorhandene Funktionalität, auch wenn es etwas overhead. Schreiben Sie Ihre eigene Methode haben könnte, den gleichen overhead-Kosten, ohne die gleichen level testen und Vertrauenwie würden Sie das hier? Der Benutzer wird gefragt, für eine factory-Methode, ein neues Objekt zu erstellen.
_replace()
Super funktioniert auf einem Instanz, aber das ist nicht das, was verlangt wird, hier.InformationsquelleAutor Martijn Pieters
Zwei Dinge: Erstens, du bist nicht wirklich viel aus namedtuple hier, soweit ich das sagen kann. Vielleicht sollten Sie also wechseln Sie einfach zu einer normalen Klasse. Auch können Sie nicht überlasten den
Zweite, andere Möglichkeiten, die vielleicht helfen, mit Ihrem problem:
Factory design pattern - anstatt die verschiedenen Parameter in den Konstruktor, die haben eine Klasse, nimmt verschiedene Arten von Parametern und ruft den Konstruktor mit entsprechenden Argumenten, außerhalb des Objekts.
recordtype - einen änderbaren namedtuple, erlaubt standardmäßig, aber würde auch Sie schreiben Ihre Unterklasse die Art und Weise Sie ursprünglich wollte.
Haufen - nicht gerade eine benannte Tupel, aber Sie können erstellen eine etwas willkürliche Zuordnung von Objekten.
InformationsquelleAutor Corley Brigman
Gibt es ein workaround zum ändern der attribute eines namedtuple.
Konnte nicht die neue Instanz zugewiesen werden, um die alte variable?
Wenn Sie verfolgen, alle Variablen zur Laufzeit, der Punkt, an dem ursprünglichen Tupel, dann ja.
InformationsquelleAutor chahuja
Ich schlage vor, Sie verwenden die
_replace
MethodeInformationsquelleAutor Yonatan Simson