39 votes

Quelque chose à propos de «namedtuple» a-t-il changé dans 3.5.1?

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

Sur 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
 

On dirait que quelque chose sur namedtuple changé (ou peut-être que c'était quelque chose sur vars() ?).

Était-ce intentionnel? Ne sommes-nous pas censés utiliser ce modèle pour convertir des tuples nommés en dictionnaires?

35voto

ShadowRanger Points 44

Par Python le bug #24931:

[__dict__] disparu parce qu'il était fondamentalement brisé en Python 3, donc il a dû être retiré. Offrant __dict__ a éclaté sous-classement et produit des comportements bizarres.

La révision qui a fait le changement

Plus précisément, les sous-classes sans __slots__ défini ci se comporte bizarrement:

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

Utiliser ._asdict().

12voto

Chad S. Points 3994

À partir de la docs

Nommé tuple les instances n'ont pas par exemple des dictionnaires, de sorte qu'ils sont légers et ne nécessitent pas plus de mémoire que les n-uplets.

Les docs (et help(namedtuple)) disent utiliser c._asdict() convertir dict.

9voto

jonrsharpe Points 34770

__dict__ été implémenté en tant que @property et a été supprimé; vous pouvez voir le changement dans le code source:

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)
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X