Reputation: 12672
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?
Upvotes: 39
Views: 4745
Reputation: 155323
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.
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()
.
Upvotes: 35
Reputation: 121944
__dict__
was implemented as a @property
and has been removed; you can see the change in the source code:
def __repr__(self):
'Return a nicely formatted representation string'
return self.__class__.__name__ + '({repr_fmt})' % self
@property
def __dict__(self):
'A new OrderedDict mapping field names to their values'
return OrderedDict(zip(self._fields, self))
def _asdict(self):
'Return a new OrderedDict which maps field names to their values.'
return self.__dict__
def __getnewargs__(self):
'Return self as a plain tuple. Used by copy and pickle.'
return tuple(self)
def __getstate__(self):
'Exclude the OrderedDict from pickling'
return None
def __repr__(self):
'Return a nicely formatted representation string'
return self.__class__.__name__ + '({repr_fmt})' % self
def _asdict(self):
'Return a new OrderedDict which maps field names to their values.'
return OrderedDict(zip(self._fields, self))
def __getnewargs__(self):
'Return self as a plain tuple. Used by copy and pickle.'
return tuple(self)
Upvotes: 9