[Python-ideas] Syntax for key-value iteration over mappings

Chris Angelico rosuav at gmail.com
Tue Jul 28 06:25:17 CEST 2015


On Tue, Jul 28, 2015 at 2:05 PM, Steven D'Aprano <steve at pearwood.info> wrote:
> Bottom line:
>
> Can you give a non-contrived, non-toy, practical example of where
> someone might want to seemlessly interchange (key,value) pairs from a
> mapping and (index,item) pairs from a sequence and expect to do
> something useful? Toy programming exercises like "print a table of
> key/index and value/item" aside:
>
>     0   1.0
>     1   2.0
>     2   4.0
>     3   16.0
>
> That's a nice exercise for beginners, but doesn't justify new syntax.

The most common case where you need the keys as well as the values is
when you're working with parallel structures. Here's one with lists:

tags = ["p", "li", "div", "body"]
weights = [50, 30, 60, 10]
counts = [0]*4

for idx, tag in enumerate(tags):
    if blob.find(tag) > weights[idx]:
        counts[idx] += 1

Yes, there are other ways you can structure this, but sometimes other
considerations mean it's better to keep them separate and then iterate
together. For read-only iteration you can of course zip() them
together, but if you need to update something, that's a bit harder. In
fact, that's probably a use-case as well, although I've never
personally used it in real-world code:

for idx, val in some_list:
    if condition:
        some_list[idx] *= whatever

Now here's a dictionary-based equivalent:

# Parallel iteration/mutation
questions = {
    "color": "What color would you like your bikeshed to be?",
    "size": "How many bikes do you need to house?",
    "material": "Should the shed be made of metal, wood, or paper?",
    "location": "Whose backyard should we not build this in?",
}
defaults = {"color": "red", "size": "2", "material": "wood",
"location": "City Hall"}
answers = {}
for kwd, msg in questions.items():
    response = input("%s [%s] " % (msg, defaults[kwd]))
    if response == "q": break # see, can't use a list comp here
    answers[kwd] = response or defaults[kwd]

You could think of this as a sequence (tuple or list), or as a keyword
mapping. Both ways make reasonable sense, and either way, you need to
know what the key/index is that you're working on.

> But, you're proposing this. It shouldn't be up to me to prove that it's
> not useful. It should be up to you to prove that it is.

Well, I'm not pushing for this to be added to the language. I'm aiming
much lower than that: merely that the idea is internally consistent,
and satisfies the OP's need. I fully expect it to still be YAGNI
rejected, but I believe it makes sense to ask the question, at least.

ChrisA


More information about the Python-ideas mailing list