I am trying to add a __dict__
member to classes generated by namedtuple. (__dict__
is present in python 2.7.3, but was removed in 2.7.5. See http://bugs.python.org/issue15535. It is present and documented in python 3.3.) My code uses vars(nametuple_object), which is based on __dict__
. I would like to patch the class when needed.
Here is what I have tried:
# Applies to Python 2.7.5 +
C = namedtuple('C', ['x', 'y'])
if not hasattr(C, '__dict__'):
C.__dict__ = property(C._asdict)
This does not work because C inherits a __dict__
, so hasattr is always true and (when forced) the property assignment returns:
Traceback (most recent call last):
File "namedtuple_dict.py", line 8, in <module>
C.__dict__ = property(C._asdict)
AttributeError: attribute '__dict__' of 'type' objects is not writable
Perhaps, is there a way to refer to C members that are not inherited?
SOLUTION
Here is my namedtuple wrapper that uses rdb's suggestion of just inheriting from the namedtuple class rather than trying to modify it:
def namedtuple_with_dict(typename, field_names, **kwargs):
cls = namedtuple(typename, field_names, **kwargs)
return type(typename, (cls,), {'__dict__': property(cls._asdict)})
namedtuple sets __slots__ to an empty tuple, which is specifically to avoid creating a __dict__ for the sake of memory optimisation. This means that it does not and cannot have __dict__ by its very design. You cannot assign __dict__, or define any new fields for that matter when __slots__ is present.
This does not apply to derived classes, though, so you can do:
CBase = namedtuple('C', ['x', 'y'])
class C(CBase):
__dict__ = property(CBase._asdict)
print C(1, 2).__dict__
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