I have the following named tuple:
from collections import namedtuple ReadElement = namedtuple('ReadElement', 'address value')
and then I want the following:
LookupElement = namedtuple('LookupElement', 'address value lookups')
There is duplication between the two namedtuples, how can I subclass ReadElement to contain an additional field?
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)
However the tuple is created there an then in the new statement, if I modify self to be a list I will loose type information, how can I avoid this?
Since a named tuple is a tuple, and tuples are immutable, it is impossible to change the value of a field. In this case, we have to use another private method _replace() to replace values of the field. The _replace() method will return a new named tuple.
DataClass is slower than others while creating data objects (2.94 µs). NamedTuple is the faster one while creating data objects (2.01 µs). An object is slower than DataClass but faster than NamedTuple while creating data objects (2.34 µs).
To create a named tuple, import the namedtuple class from the collections module. The constructor takes the name of the named tuple (which is what type() will report), and a string containing the fields names, separated by whitespace. It returns a new namedtuple class for the specified fields.
It allows you to access the coordinates using the dot notation, which is convenient, readable, and explicit. You can also use indices to access the value of each coordinate. Note: It's important to note that, while tuples and named tuples are immutable, the values they store don't necessarily have to be immutable.
You can subclass a namedtuple
-produced class, but you need to study the generated class more closely. You'll need to add another __slots__
attribute with the extra fields, update the _fields
attribute, create new __repr__
and _replace
methods (they hardcode the field list and class name) and add extra property
objects for the additional fields. See the example in the documentation.
That's all a little too much work. Rather than subclass, I'd just reuse the somenamedtuple._fields
attribute of the source type:
LookupElement = namedtuple('LookupElement', ReadElement._fields + ('lookups',))
The field_names
argument to the namedtuple()
constructor doesn't have to be a string, it can also be a sequence of strings. Simply take the _fields
and add more elements by concatenating a new tuple.
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')
This does mean that the extended type is not a subclass of the base type. If you must have a class hierarchy, then rather than try to make named tuples fit that model, I'd switch to using dataclasses instead. Dataclasses can serve the same purpose in most usecases named tuples are used for, but can easily be subclassed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With