Obtenir un sous-ensemble d’un dictionnaire Python

J’ai un dictionnaire:

{'key1':1, 'key2':2, 'key3':3} 

Je dois transmettre un sous-ensemble de ce dictionnaire à un code tiers. Il ne veut qu’un dictionnaire contenant des clés ['key1', 'key2', 'key99'] et s’il obtient une autre clé (par exemple 'key3' ), il explose dans un désordre désagréable. Le code en question est hors de mon contrôle, donc je suis obligé de nettoyer mon dictionnaire.

Quel est le meilleur moyen de limiter un dictionnaire à un ensemble de clés?

Étant donné l’exemple de dictionnaire et les clés autorisées ci-dessus, je veux:

 {'key1':1, 'key2':2} 

 In [38]: adict={'key1':1, 'key2':2, 'key3':3} In [41]: dict((k,adict[k]) for k in ('key1','key2','key99') if k in adict) Out[41]: {'key1': 1, 'key2': 2} 

Dans Python3 (ou Python2.7 ou ultérieur), vous pouvez le faire avec une compréhension de dict :

 >>> {k:adict[k] for k in ('key1','key2','key99') if k in adict} {'key2': 2, 'key1': 1} 
 dict(filter(lambda i:i[0] in validkeys, d.iteritems())) 

Dans Python moderne (2.7 +, 3.0 +), utilisez une compréhension de dictionnaire:

 d = {'key1':1, 'key2':2, 'key3':3} included_keys = ['key1', 'key2', 'key99'] {k:v for k,v in d.items() if k in included_keys} 

Ma façon de le faire est.

 from operator import itemgetter def subdict(d, ks): return dict(zip(ks, itemgetter(*ks)(d))) my_dict = {'key1':1, 'key2':2, 'key3':3} subdict(my_dict, ['key1', 'key3']) 

Mettre à jour

Je dois admettre que l’implémentation ci-dessus ne gère pas le cas où la longueur de ks est 0 ou 1. Le code suivant gère la situation et il n’est plus un one-liner.

 def subdict(d, ks): vals = [] if len(ks) >= 1: vals = itemgetter(*ks)(d) if len(ks) == 1: vals = [vals] return dict(zip(ks, vals)) 

Une autre solution sans si dans la compréhension de dict.

 >>> a = {'key1':1, 'key2':2, 'key3':3} >>> b = {'key1':1, 'key2':2} >>> { k:a[k] for k in b.keys()} {'key2': 2, 'key1': 1} 

Avec une classe complexe Myclass étant une sous-classe de collections.UserDict . Pour en sélectionner un sous-ensemble, c’est-à-dire conserver toutes ses propriétés de conteneur, il est pratique de définir une méthode, par exemple nommée sub comme telle:

 def sub(self, keys): subset = Myclass() # no arguments; works if defined with only keyword arguments for key in keys: subset[key] = self[key] return subset 

Il est ensuite utilisé comme Myclass.sub([key1, key2 ...] )