[Python-ideas] Add a method to get the subset of a dictionnary.

Steven D'Aprano steve at pearwood.info
Sat Nov 12 03:32:33 EST 2016


On Wed, Oct 12, 2016 at 06:06:51PM +0200, Enguerrand Pelletier wrote:
> Hi all,
> 
> It always bothered me to write something like this when i want to strip 
> keys from a dictionnary in Python:
> 
> a = {"foo": 1, "bar": 2, "baz": 3, "foobar": 42}
> interesting_keys = ["foo", "bar", "baz"]
> b = {k, v for k,v in a.items() if k in interesting_keys}

(You have a small typo: should be "k: v" not "k, v".)

Why does it bother you? It is simple, easy to understand, and explict.


> Wouldn't it be nice to have a syntactic sugar such as:

Syntactic sugar is not really the right term, "syntactic sugar" means a 
special form of syntax as a short-cut for something longer. This is not 
special syntax, it is just a method.


> b = a.subset(interesting_keys)

Personally, I have never missed this method, but if I did, it would be 
easy to make a helper function:

def subset(adict, keys):
    """Return a new dict from existing keys."""
    return {k: v for k,v in a.items() if k in keys}


Not every simple helper function needs to be built-in to the class. That 
is the beauty of Python, you can make your own helper functions, once 
you give up the idea that everything needs to be a method.

There are some problems with making this a method. To start with, it 
means that every dict and mapping would have to support it. Perhaps that 
is acceptible, but it does mean that the question is bigger than just 
dict. It also involves:

    ChainMap
    Counter
    Mapping
    MutableMapping
    OrderedDict
    UserDict
    defaultdict

at the very least. (Perhaps this is easy to implement, by just adding 
this to the Mapping ABC and letting everything else inherit from that. 
But even so, it increases the complexity of the entire Mapping ABC and 
all its classes.)

But a bigger problem with making this a built-in dict method is deciding 
exactly what it should do. Here are some options:

- should the method return a new dict, or modify the existing dict?

- should it keep the "interesting keys" or remove them?

- is it an error if one of the interesting keys is missing?

- or should it be silently skipped?

- or automatically added? using what value?

Whatever options we pick here, you can be sure that some people will 
want a different set of options.

Unless we are sure that one combination is much more common than the 
other combinations, we're better off letting people write their own 
helper functions that behave exactly as they want:

def subset(d, keys):
    # Version which raises if any of the keys are missing
    return {key: d[key] for key in keys}



-- 
Steve


More information about the Python-ideas mailing list