Skip to content Skip to sidebar Skip to footer

Python Collections.namedtuple() Confusion

The documentation says that any python valid identifier can be a field_name, except those which start with underscore, that's fine. If the rename argument is true, it replaces inva

Solution 1:

The reason you cannot use underscores at the start of names is that there is a chance these would clash with the method names the class provides (such as _replace).

Because just numbers are not valid Python names, any name not valid as an attribute (so not a valid Python identifier or a name starting with an underscore) are replaced by underscore + position number. This means these generated names cannot clash with valid names nor with the provided methods on the type.

This is not inconsistent with what names you are allowed to pick; it is in fact the perfect fallback given the restrictions. In addition, the name thus generated is easily deduced; the attribute for such values is directly related to their index in the tuple.

As for setting verbose to True, it does what it says on the tin. The source code of the generated namedtuple class is printed to sys.stdout:

>>> from collections import namedtuple
>>> namedtuple('foo', 'bar baz', verbose=True)
classfoo(tuple):
    'foo(bar, baz)'

    __slots__ = ()

    _fields = ('bar', 'baz')

    def__new__(_cls, bar, baz):
        'Create new instance of foo(bar, baz)'return _tuple.__new__(_cls, (bar, baz))

    @classmethoddef_make(cls, iterable, new=tuple.__new__, len=len):
        'Make a new foo object from a sequence or iterable'
        result = new(cls, iterable)
        iflen(result) != 2:
            raise TypeError('Expected 2 arguments, got %d' % len(result))
        return result

    def__repr__(self):
        'Return a nicely formatted representation string'return'foo(bar=%r, baz=%r)' % self

    def_asdict(self):
        'Return a new OrderedDict which maps field names to their values'return OrderedDict(zip(self._fields, self))

    def_replace(_self, **kwds):
        'Return a new foo object replacing specified fields with new values'
        result = _self._make(map(kwds.pop, ('bar', 'baz'), _self))
        if kwds:
            raise ValueError('Got unexpected field names: %r' % kwds.keys())
        return result

    def__getnewargs__(self):
        'Return self as a plain tuple.  Used by copy and pickle.'returntuple(self)

    __dict__ = _property(_asdict)

    def__getstate__(self):
        'Exclude the OrderedDict from pickling'pass

    bar = _property(_itemgetter(0), doc='Alias for field number 0')

    baz = _property(_itemgetter(1), doc='Alias for field number 1')


<class'__main__.foo'>

This lets you inspect what exactly was generated for your class.

Post a Comment for "Python Collections.namedtuple() Confusion"