I have a tiny class that extends a namedtuple
, but the __dict__
property of its instances is always returning empty.
Point = namedtuple('Point', 'x y')
p1 = Point(20, 15)
print(p1, p1.__dict__)
# Point(x=20, y=15) OrderedDict([('x', 20), ('y', 15)]) <--- ok
class SubPoint(Point): pass
p2 = SubPoint(20, 15)
print(p2, p2.__dict__)
# SubPoint(x=20, y=15) {} <--- why is it empty?
p2
has the attributes, but its __dict__
is empty. They are listed correctly with dir()
, though, which is strange. Note this work correctly when SubPoint
extends a vanilla class.
What is happening, and how do I list the attributes in my subclass instance?
To see why __dict__
doesn't work, check the answer by Ashwini Chaudhary. This answer covers the second part of the question (how to list namedtuple attributes).
To list namedtuple attributes, there are _fields
and _asdict
:
>>> import collections as c
>>> Point = c.namedtuple("Point", ["x", "y"])
>>> p1 = Point(20, 15)
>>> print(p1._fields)
('x', 'y')
>>> print(p1._asdict())
{'x': 20, 'y': 15}
>>> class SubPoint(Point): pass
...
>>> p2 = SubPoint(20, 15)
>>> print(p2._fields)
('x', 'y')
>>> print(p2._asdict())
{'x': 20, 'y': 15}
Note that _fields
is defined on the class, so you can also do:
>>> print(SubPoint._fields)
('x', 'y')
Obviously, _asdict
needs an instance so it can use the values.
I used Python 3.9.7 for the examples, I'm not exactly sure when this stuff was added (maybe someone who knows can comment).