1

For some reason the following code felt a bit cumbersome to me, given all the syntactic sugar I keep finding in Python, so I thought enquire if there's a better way:

pictures = list_of_random_pictures()
invalid_pictures = {}
for picture in pictures:
    if picture_invalid(picture):
        if not invalid_pictures.get(picture.album.id):
            invalid_pictures[picture.album.id] = []
        invalid_pictures[picture.album.id].append(picture)

So just to clarify, I'm wondering if there's a more readable way to take care of the last 3 lines above. As I'm repeating invalid_pictures[picture.album.id] 3 times, it just seems unnecessary if it's at all avoidable.

EDIT: Just realized my code above will KeyError, so I've altered it to handle that.

2 Answers 2

4

There is, in fact, an object in the standard library to deal exactly with that case: collections.defaultdict

It takes as its argument either a type or function which produces the default value for a missing key.

from collections import defaultdict

invalid_pictures = defaultdict(list)
for picture in pictures:
    if picture_invalid(picture):
        invalid_pictures[picture.album.id].append(picture)
Sign up to request clarification or add additional context in comments.

Comments

2

Although I do find Joel's answer to be the usual solution, there's an often overlooked feature that is sometimes preferrable. when a default value isn't particularly desired is to use dict.setdefault(), when inserting the default is something of an exception (and collections.defaultdict is suboptimal. your code, adapted to use setdefault() would be

pictures = list_of_random_pictures()
invalid_pictures = {}
for picture in pictures:
    if picture_invalid(picture):
        invalid_pictures.setdefault(picture.album.id, []).append(picture)

although this has the downside of creating a lot of (probably unused) lists, so in the particular case of setting the default to a list, it's still often better to use a defaultdict, and then copy it to a regular dict to strip off the default value. This doesn't particularly apply to immutable types, such as int or str.

For example, pep-333 requires that the environ variable be a regular dict, not a subclass or instance of collections.Mapping, but a real, plain ol' dict. Another case is when you aren't so much as passing through an iterator and applying to a flat mapping; but each key needs special handling, such as when applying defaults to a configuration.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.