Search code examples
pythontypeerrorpython-3.5namedtuple

Did something about `namedtuple` change in 3.5.1?


On Python 3.5.0:

>>> from collections import namedtuple
>>> cluster = namedtuple('Cluster', ['a', 'b'])
>>> c = cluster(a=4, b=9)
>>> c
Cluster(a=4, b=9)
>>> vars(c)
OrderedDict([('a', 4), ('b', 9)])

On Python 3.5.1:

>>> from collections import namedtuple
>>> cluster = namedtuple('Cluster', ['a', 'b'])
>>> c = cluster(a=4, b=9)
>>> c
Cluster(a=4, b=9)
>>> vars(c)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: vars() argument must have __dict__ attribute

Seems like something about namedtuple changed (or maybe it was something about vars()?).

Was this intentional? Are we not supposed to use this pattern for converting named tuples into dictionaries anymore?


Solution

  • Per Python bug #24931:

    [__dict__] disappeared because it was fundamentally broken in Python 3, so it had to be removed. Providing __dict__ broke subclassing and produced odd behaviors.

    Revision that made the change

    Specifically, subclasses without __slots__ defined would behave weirdly:

    >>> Cluster = namedtuple('Cluster', 'x y')
    >>> class Cluster2(Cluster):
        pass
    >>> vars(Cluster(1,2))
    OrderedDict([('x', 1), ('y', 2)])
    >>> vars(Cluster2(1,2))
    {}
    

    Use ._asdict().