This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Make iteration over dict_items yield namedtuples
Type: enhancement Stage: resolved
Components: Library (Lib) Versions: Python 3.8
process
Status: closed Resolution: rejected
Dependencies: Superseder:
Assigned To: Nosy List: Richard Neumann, eric.smith, r.david.murray, rhettinger, serhiy.storchaka
Priority: normal Keywords:

Created on 2017-11-09 16:24 by Richard Neumann, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Messages (5)
msg305970 - (view) Author: Richard Neumann (Richard Neumann) Date: 2017-11-09 16:24
Currently, iterating over dict_items will yield plain tuples, where the first item will be the key and the second item will be the respective value.

This has some disadvantages when e.g. sorting dict items by value and key:

    def sort_by_value_len(dictionary):
        return sorted(dictionary.items(), key=lambda item: (len(item[1]), item[0]))

I find this index accessing extremely unelegant and unnecessarily hard to read.

If dict_items would instead yield namedtuples like

    DictItem = namedtuple('DictItem', ('key', 'value'))

this would make constructs like

    def sort_by_value_len(dictionary):
        return sorted(dictionary.items(), key=lambda item: (len(item.value), item.key))

possible and increase code clarity a lot.
Also, namedtuples mimic the behaviour of plain tuples regarding unpacking and index accessing, so that backward-compatipility should exist.
msg305972 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2017-11-09 17:22
Oh, no! Tuples is one of the most charming features of Python. Use tuples, folk!
msg305986 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2017-11-09 21:36
I cannot imagine this ever happening, for performance reasons.

You should write your own wrapper around items, if you want this behavior.
msg306028 - (view) Author: Richard Neumann (Richard Neumann) Date: 2017-11-10 12:55
Maybe there is no need to sacrifice performance, if a new, optional keyword argument would be introduced to dict.items():

    def items(self, named=False):
        if named:
            <yield namedtuples>
        else:
            <current behaviour>

Currently I need to define a namedtuple everywhere I do this and starmap the dicts' items.

It'd be nice to have this option built-in or a new collections class like:

    from collections import namedtuple
    from itertools import starmap


    DictItem = namedtuple('DictItem', ('key', 'value'))


    class NamedDict(dict):
        """Dictionary that yields named tuples on item iterations."""

        def items(self):
            """Yields DictItem named tuples."""
            return starmap(DictItem, super().items())
msg306030 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2017-11-10 13:28
This is not something it is worth complicating the dict API or collections for.  If you want the feature in your code, implement your subclass in your own utility library.

If you disagree with this decision, please bring it up on the python-ideas mailing list for further analysis, but I'm guessing you won't get much traction.
History
Date User Action Args
2022-04-11 14:58:54adminsetgithub: 76173
2017-11-10 13:28:26r.david.murraysetstatus: open -> closed

nosy: + r.david.murray
messages: + msg306030

resolution: rejected
stage: resolved
2017-11-10 12:55:54Richard Neumannsetmessages: + msg306028
2017-11-09 21:36:34eric.smithsetnosy: + eric.smith
messages: + msg305986
2017-11-09 17:22:26serhiy.storchakasetnosy: + rhettinger, serhiy.storchaka
messages: + msg305972
2017-11-09 16:24:13Richard Neumanncreate