Skip to content

Instantly share code, notes, and snippets.

@WarrenWeckesser
Created June 8, 2020 17:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save WarrenWeckesser/5230e3fc24c83f64b54bdcc212354e64 to your computer and use it in GitHub Desktop.
Save WarrenWeckesser/5230e3fc24c83f64b54bdcc212354e64 to your computer and use it in GitHub Desktop.
Scratch work for a subclass of namedtuple with additional attributes.
from collections import namedtuple
def make_namedtuple_bunch1(typename, field_names, extra_field_names):
namedtuple_type = namedtuple(typename, field_names)
def __new__(cls, *args, **kwds):
# Pull out any keyword parameters that are not in the fields of
# the namedtuple.
extra_kwds = {}
for name in list(kwds):
if name not in cls._fields:
extra_kwds[name] = kwds.pop(name)
for name in cls._fields:
if name not in kwds:
raise TypeError(f'missing parameter {name!r}')
for name in extra_kwds:
if name not in cls._extra_fields:
raise TypeError(f'unexpected parameter {name!r}')
for name in cls._extra_fields:
if name not in extra_kwds:
raise TypeError(f'missing parameter {name!r}')
obj = namedtuple_type.__new__(cls, *args, **kwds)
# Update the object's attributes with the extra fields.
obj.__dict__.update(extra_kwds)
return obj
def __repr__(self):
s = namedtuple_type.__repr__(self)
if hasattr(self, '_extra_fields'):
s = s.rstrip(')')
s += ', ' + ', '.join([name + '=' + repr(self.__dict__[name])
for name in self._extra_fields])
s += ')'
return s
def __setattr__(self, name, value):
raise AttributeError("can't set attribute")
cls = type(typename, (namedtuple_type,),
dict(__new__=__new__,
__repr__=__repr__,
__setattr__=__setattr__,
_extra_fields=tuple(extra_field_names)))
return cls
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment