libreria - namedtuple python
Python: Extendiendo una tupla nombrada predefinida (2)
Tengo la siguiente tupla nombrada:
from collections import namedtuple
ReadElement = namedtuple(''ReadElement'', ''address value'')
Y luego quiero lo siguiente:
LookupElement = namedtuple(''LookupElement'', ''address value lookups'')
Hay duplicación entre los dos elementos nombrados, ¿cómo puedo subclase ReadElement para contener un campo adicional?
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)
Sin embargo, la tupla se crea allí y luego en la nueva declaración, si me modifico para ser una lista, perderé información de tipo, ¿cómo puedo evitar esto?
Es bastante fácil pegar algo que le permite componer muestras nombradas a partir de otras muestras nombradas, así como introducir nuevos campos.
def extended_namedtuple(name, source_fields):
assert isinstance(source_fields, list)
new_type_fields = []
for f in source_fields:
try:
new_type_fields.extend(f._fields)
except:
new_type_fields.append(f)
return namedtuple(name, new_type_fields)
# source types
Name = namedtuple(''Name'', [''first_name'', ''last_name''])
Address = namedtuple(''Address'', [''address_line1'', ''city''])
# new type uses source types and adds additional ID field
Customer = extended_namedtuple(''Customer'', [''ID'', Name, Address])
# using the new type
cust1 = Customer(1, ''Banana'', ''Man'', ''29 Acacia Road'', ''Nuttytown'')
print(cust1)
Esto da como resultado lo siguiente:
Customer(ID=1, first_name=''Banana'', last_name=''Man'', address_line1=''29 Acacia Road'', city=''Nuttytown'')
Puede namedtuple
una subclase de una clase producida por un grupo de namedtuple
, pero necesita estudiar la clase generada más de cerca. Deberá agregar otro atributo __slots__
con los campos adicionales, actualizar el atributo _fields
, crear nuevos métodos __repr__
y _replace
(codifican la lista de campos y el nombre de la clase) y agregar objetos de property
adicionales para los campos adicionales. Vea el ejemplo en la documentación .
Eso es demasiado trabajo. En lugar de subclase, simplemente reutilizaría el atributo somenamedtuple._fields
del tipo fuente:
LookupElement = namedtuple(''LookupElement'', ReadElement._fields + (''lookups'',))
El argumento field_names
para el constructor namedtuple()
no tiene que ser una cadena, también puede ser una secuencia de cadenas. Simplemente tome los _fields
y agregue más elementos concatenando una nueva tupla.
Manifestación:
>>> 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'')
Esto significa que el tipo extendido no es una subclase del tipo base. Si debe tener una jerarquía de clases, en lugar de tratar de hacer que las tuplas con nombre se ajusten a ese modelo, me cambio a usar dataclasses en dataclasses lugar. Las clases de datos pueden servir para el mismo propósito en la mayoría de los casos en que se usan las tuplas con nombre, pero se pueden clasificar en subclases fácilmente.