web-dev-qa-db-fra.com

defaultdict avec la valeur par défaut 1?

Je suis nouveau sur python et j'ai lu un extrait de code d'un endroit. C'est une implémentation du tri par comptage.

Le code est le suivant:

from collections import defaultdict
def sort_colors(A):
    ht = {}                        # a hash map
    ht = defaultdict(lambda:0, ht) # with default value 1
    for i in A:
         ht[i] += 1
    ret = []
    for k in [0, 1, 2]:
        ret.extend([k]*ht[k])
    return ret

Comme dans les deux premières lignes de la fonction, c'est

ht = {}
ht = defaultdict(lambda:0, ht)

Je ne suis pas tout à fait clair sur cette initialisation. Pourriez-vous m'aider à le comprendre? et aussi, devons-nous simplement remplacer ces deux lignes par les suivantes?

ht = defaultdict(int) # default value 0
30
chancyWu

Réponse courte (selon la réponse de Montaro ci-dessous)

defaultdict(lambda:1)

Réponse longue sur le fonctionnement de defaultdicts

ht = {}
ht = defaultdict(lambda:0, ht)

defaultdicts sont différents de dict en ce que lorsque vous essayez d'accéder à un dict normal avec une clé qui n'existe pas, il lève un KeyError.
defaultdict, cependant, ne génère pas d'erreur: il crée la clé pour vous à la place. Avec quelle valeur? Avec le retour du callabe vous avez passé en argument. Dans ce cas, chaque nouvelle clé sera créée avec la valeur 0 (Qui est le retour de la simple fonction lambdalambda:0), Qui se trouve également être le même retour de int(), donc dans dans ce cas, il n'y aurait aucune différence à changer la fonction par défaut en int().

Décomposer cette ligne plus en détail: ht = defaultdict(lambda:0, ht)

Le premier argument est une fonction, qui est un objet appelable. Il s'agit de la fonction qui sera appelée pour créer une nouvelle valeur pour une clé inexistante. Le deuxième argument, ht est facultatif et fait référence au dictionnaire de base sur lequel le nouveau defaultdict sera construit. Par conséquent, si ht avait des clés et des valeurs, le defaultdict aurait également ces clés avec les valeurs correspondantes. Si vous essayez d'accéder à ces clés, vous obtiendrez les anciennes valeurs. Cependant, si vous ne transmettez pas le dictionnaire de base, un tout nouveau defaultdict sera créé, et ainsi, toutes les nouvelles clés accédées recevront la valeur par défaut renvoyée par l'appelable.
(Dans ce cas, comme ht est initialement un dict vide, il n'y aurait aucune différence du tout en faisant ht = defaultdict(lambda:0), ht = defaultdict(int) ou ht = defaultdict(lambda:0, ht): ils construiraient tous le même defaultdict.

38
rafaelc

Je pense que vous pouvez simplement passer une fonction lambda qui retourne 1

d = defaultdict(lambda:1)
33
Montaro