diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst index 495cfc2c234f756..ace3328c62d9232 100644 --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -887,18 +887,22 @@ field names, the method and attribute names start with an underscore. .. method:: somenamedtuple._asdict() - Return a new :class:`OrderedDict` which maps field names to their corresponding - values: + Return a new ordered dictionary which maps field names to their + corresponding values: .. doctest:: >>> p = Point(x=11, y=22) >>> p._asdict() - OrderedDict([('x', 11), ('y', 22)]) + {'x': 11, 'y': 22} .. versionchanged:: 3.1 Returns an :class:`OrderedDict` instead of a regular :class:`dict`. + .. versionchanged:: 3.8 + Returns an :class:`dict` instead of a :class:`OrderedDict`, + since it can now keep keys the same order as namedtuple fields. + .. method:: somenamedtuple._replace(**kwargs) Return a new instance of the named tuple replacing specified fields with new diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 1c129a704429f26..0268c0199b6bfd8 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -315,6 +315,14 @@ Changes in the Python API * :class:`uuid.UUID` now uses ``__slots__``, therefore instances can no longer be weak-referenced and attributes can no longer be added. +* The :meth:`~collections.namedtuple._asdict` method returns a :class:`dict` + instead of :class:`collections.OrderedDict`, because :class:`dict` keeps + insertion order, which is the same behavior as + :class:`collections.OrderedDict`. Anyone relying on + :meth:`~collections.OrderedDict.move_to_end` will want to explicitly construct + an :class:`collections.OrderedDict`. + (Contributed by Michael Selik in :issue:`33463`.) + CPython bytecode changes ------------------------ diff --git a/Lib/collections/__init__.py b/Lib/collections/__init__.py index 4724b0edf33a7cb..1820c1b149b843c 100644 --- a/Lib/collections/__init__.py +++ b/Lib/collections/__init__.py @@ -424,8 +424,8 @@ def __repr__(self): 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)) + 'Return a new dict which maps field names to their values.' + return dict(zip(self._fields, self)) def __getnewargs__(self): 'Return self as a plain tuple. Used by copy and pickle.' diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py index 0b7cb5848b1b8ff..2416d733aebd1c6 100644 --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -331,6 +331,7 @@ def test_instance(self): self.assertEqual(p._fields, ('x', 'y')) # test _fields attribute self.assertEqual(p._replace(x=1), (1, 22)) # test _replace method self.assertEqual(p._asdict(), dict(x=11, y=22)) # test _asdict method + self.assertEqual(list(p._asdict()), ['x', 'y']) # test _asdict ordering try: p._replace(x=1, error=2) diff --git a/Misc/NEWS.d/next/Library/2018-06-29-13-30-14.bpo-33463.b_BpgK.rst b/Misc/NEWS.d/next/Library/2018-06-29-13-30-14.bpo-33463.b_BpgK.rst new file mode 100644 index 000000000000000..1dd0efd393602dc --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-06-29-13-30-14.bpo-33463.b_BpgK.rst @@ -0,0 +1,3 @@ +namedtuple._asdict returns dict instead of OrderedDict, since dict now +keeps keys in insertion order, the same as OrderedDict. Patch by Michael +Selik.