Python's namedtuple can be really useful as a lightweight, immutable data class. I like using them for bookkeeping parameters rather than dictionaries. When some more functionality is desired, such as a simple docstring or default values, you can easily refactor the namedtuple to a class. However, I've seen classes that inherit from namedtuple. What functionality are they gaining, and what performance are they losing? For example, I would implement this as
from collections import namedtuple
class Pokemon(namedtuple('Pokemon', 'name type level')):
"""
Attributes
----------
name : str
What do you call your Pokemon?
type : str
grass, rock, electric, etc.
level : int
Experience level [0, 100]
"""
__slots__ = ()
For the sole purpose of being able to document the attrs cleanly, and __slots__
is used to prevent the creation of a __dict__
(keeping the lightweight nature of namedtuples).
Is there a better recommendation of a lightweight data class for documenting parameters? Note I'm using Python 2.7.
NEW UPDATE:
In python 3.6+, you can use the new typed syntax and create a
typing.NamedTuple
. The new syntax supports all the usual python class creation features (docstrings, multiple inheritance, default arguments, methods, etc etc are available as of 3.6.1):The class objects created by this version are mostly equivalent to the original
collections.namedtuple
, except for a few details.You can also use the same syntax as the old named tuple:
Original Answer
Short answer: no, unless you are using Python < 3.5
The P3 docs seem to imply pretty clearly that unless you need to add calculated fields (i.e., descriptors), subclassing
namedtuple
is not considered the canonical approach. This is because you can update the docstrings directly (they are now writable as of 3.5!).UPDATE:
There are now a couple other compelling possibilities for lightweight data classes in the latest versions of Python.
One is
types.SimpleNamespace
(Python 3.3 and later). It is not structured likenamedtuple
, but structure isn't always necessary.One thing to note about
SimpleNamespace
: by default it is required to explicitly designate the field names when instantiating the class. This can be got around fairly easily, though, with a call tosuper().__init__
:Another intriguing option- which will be available as of Python 3.7 (not yet released)- is
dataclasses.dataclass
(see PEP 557):Note that both of these suggestions are mutable by default, and that
__slots__
is not required for either one.