2015-02-13 12 views
11

Ich habe die folgenden genannt Tupel:Python: Erweitern eines vordefinierten Namen Tupel

from collections import namedtuple 
ReadElement = namedtuple('ReadElement', 'address value') 

und dann möchte ich folgendes:

LookupElement = namedtuple('LookupElement', 'address value lookups') 

Es gibt Überschneidungen zwischen den beiden namedtuples, wie kann ich eine Unterklasse ReadElement, um ein zusätzliches Feld zu enthalten?

class LookupElement(ReadElement): 
    def __new__(self, address, value, lookups): 
     self = super(LookupElement, self).__new__(address, value) 
     l = list(self) 
     l.append(lookups) 
     return tuple(l) 

jedoch das Tupel dort angelegt wird ein dann in der neue Aussage, wenn ich selbst ändern eine Liste, die ich Typ-Informationen verlieren wird, wie kann ich das vermeiden?

Antwort

19

Sie können eine -produzierte Klasse ableiten, aber Sie müssen die generierte Klasse genauer untersuchen. Sie müssen ein weiteres __slots__ Attribut mit den zusätzlichen Feldern hinzufügen, das _fields Attribut aktualisieren, neue __repr__ und _replace Methoden erstellen (sie codieren die Feldliste und den Klassennamen) und zusätzliche property Objekte für die zusätzlichen Felder hinzufügen. Siehe die example in the documentation.

Das ist alles ein bisschen zu viel Arbeit. Anstatt Unterklasse, würde ich wieder verwenden nur die somenamedtuple._fields attribute des Quelltyp:

LookupElement = namedtuple('LookupElement', ReadElement._fields + ('lookups',)) 

Das field_names Argument für den Konstruktor namedtuple() keinen String sein muss, ist es auch eine Reihe von Strings sein kann. Nehmen Sie einfach die _fields und fügen Sie weitere Elemente hinzu, indem Sie ein neues Tupel verketten.

Demo:

>>> from collections import namedtuple 
>>> ReadElement = namedtuple('ReadElement', 'address value') 
>>> LookupElement = namedtuple('LookupElement', ReadElement._fields + ('lookups',)) 
>>> LookupElement._fields 
('address', 'value', 'lookups') 
>>> LookupElement('addr', 'val', 'lookup') 
LookupElement(address='addr', value='val', lookups='lookup') 
+0

das ist genau das, was ich wollte, dank – Har

+0

Dies ist, was die Dokumentation empfehlen zu tun, aber was ist, wenn Sie eine benutzerdefinierte namedtuple mit einem generierten Feld haben? – Ethereal

+0

@Ethereal: Alle namedtuple-Klassen sind benutzerdefiniert. Das '_fields'-Attribut wird weiterhin die tatsächlichen Felder in der Klasse widerspiegeln. –