2015-02-13 6 views
11

Я следующее имя кортеж:Python: Расширение предопределенного имени кортежа

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

и затем я хочу следующего:

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

Существует дублирование между два namedtuples, как я могу подкласс ReadElement содержать дополнительное поле?

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) 

Однако кортеж создается там, то в новом заявления, если я могу изменить себя, чтобы быть список, который я потеряет информацию о типе, как я могу избежать этого?

ответ

19

Вы можете создать класс класса namedtuple, но вам нужно более внимательно изучить сгенерированный класс. Вам нужно будет добавить еще один атрибут __slots__ с дополнительными полями, обновить атрибут _fields, создать новые методы __repr__ и _replace (они жестко задают список полей и имя класса) и добавлять дополнительные property объекты для дополнительных полей. См. example in the documentation.

Это все слишком много работы. Вместо того подкласса, я бы просто использовать повторно somenamedtuple._fields attribute типа источника:

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

field_names аргумент namedtuple() конструктор не должен быть строкой, она также может быть последовательность строк. Просто возьмите _fields и добавьте еще несколько элементов, объединив новый кортеж.

Демо:

>>> 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

то будет именно то, что я хотел, спасибо – Har

+0

Это то, что документы предлагают делать, но что, если у вас есть собственный namedtuple с порожденным полем? – Ethereal

+0

@Ethereal: все классы namedtuple являются обычными. Атрибут '_fields' по-прежнему будет отображать фактические поля в классе. –