ordereddict example dict python python-3.5 namedtuple

python - example - ¿Algo sobre `namedtuple` cambió en 3.5.1?



python dict (3)

De los docs

Las instancias de tuplas nombradas no tienen diccionarios por instancia, por lo que son livianas y no requieren más memoria que las tuplas normales.

Los docs (y la help(namedtuple) ) dicen que se use c._asdict() para convertir a un dict.

En 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)])

En 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

Parece que algo sobre namedtuple cambió (o tal vez fue algo sobre vars() ?).

¿Fue esto intencional? ¿No se supone que debemos usar este patrón para convertir tuplas con nombres en diccionarios más?


Por error de Python # 24931 :

[ __dict__ ] desapareció porque estaba fundamentalmente roto en Python 3, por lo que tuvo que ser eliminado. Proporcionar __dict__ rompió las subclases y produjo comportamientos extraños.

Revisión que hizo el cambio

Específicamente, las subclases sin __slots__ definidas se comportarían de manera extraña:

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

Use ._asdict() .


__dict__ se implementó como @property y se ha eliminado; puedes ver el cambio en el código fuente:

3.5.0 :

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

3.5.1 :

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)