Existence of mutable named tuple in Python?
mutable, namedtuple, python, python-3.x
Solution
There is a mutable alternative to `collections.namedtuple` – recordclass. It can be installed from PyPI:
pip3 install recordclass
It has the same API and memory footprint as `namedtuple` and it supports assignments (It should be faster as well). For example:
from recordclass import recordclass
Point = recordclass('Point', 'x y')
>>> p = Point(1, 2)
>>> p
Point(x=1, y=2)
>>> print(p.x, p.y)
1 2
>>> p.x += 2; p.y += 3; print(p)
Point(x=3, y=5)
`recordclass` (since 0.5) support typehints:
from recordclass import recordclass, RecordClass
class Point(RecordClass):
x: int
y: int
>>> Point.__annotations__
{'x':int, 'y':int}
>>> p = Point(1, 2)
>>> p
Point(x=1, y=2)
>>> print(p.x, p.y)
1 2
>>> p.x += 2; p.y += 3; print(p)
Point(x=3, y=5)
There is a more complete example (it also includes performance comparisons).
`Recordclass` library now provides another variant -- `recordclass.make_dataclass` factory function. It support dataclasses-like API (there are module level functions `update`, `make`, `replace` instead of `self._update`, `self._replace`, `self._asdict`, `cls._make` methods).
from recordclass import dataobject, make_dataclass
Point = make_dataclass('Point', [('x', int), ('y',int)])
Point = make_dataclass('Point', {'x':int, 'y':int})
class Point(dataobject):
x: int
y: int
>>> p = Point(1, 2)
>>> p
Point(x=1, y=2)
>>> p.x = 10; p.y += 3; print(p)
Point(x=10, y=5)
`recordclass` and `make_dataclass` can produce classes, whose instances occupy less memory than `__slots__`-based instances. This can be important for the instances with attribute values, which has not intended to have reference cycles. It may help reduce memory usage if you need to create millions of instances. Here is an illustrative example.
Problem
Can anyone amend namedtuple or provide an alternative class so that it works for mutable objects? Primarily for readability, I would like something similar to namedtuple that does this: ``` from Camelot import namedgroup Point = namedgroup('Point', ['x', 'y']) p = Point(0, 0) p.x = 10 >>> p Point(x=10, y=0) >>> p.x *= 10 Point(x=100, y=0) ``` It must be possible to pickle the resulting object. And per the characteristics of named tuple, the ordering of the output when represented must match the order of the parameter list when constructing the object.
Related problems
- What is the meaning of single and double underscore before an object name?
- Dictionary vs Object - which is more efficient and why?
- Avoid Pylint warning E1101: 'Instance of .. has no .. member' for class with dynamic attributes
- Usage of __slots__?
- What is the difference between __init__ and __call__?
- Purpose of __repr__ method?
- How to build a basic iterator?
- What does the "yield" keyword do in Python?