web-dev-qa-db-fra.com

Existe-t-il une différence entre utiliser un dictal littéral et un constructeur de dict?

En utilisant PyCharm, j’ai remarqué qu’il propose de convertir un dict literal:

d = {
    'one': '1',
    'two': '2',
}

dans un constructeur de dict:

d = dict(one='1', two='2')

Ces différentes approches diffèrent-elles de manière significative?

(En écrivant cette question, j'ai remarqué que l'utilisation de dict() semble impossible de spécifier une clé numérique. d = {1: 'one', 2: 'two'} est possible, mais il est évident que dict(1='one' ...) ne l'est pas. Rien d'autre?)

182
maligree

Je pense que vous avez souligné la différence la plus évidente. Mis à part cela,

le premier n'a pas besoin de chercher dict ce qui devrait le rendre un peu plus rapide

le second cherche dict dans locals(), puis globals(), puis trouve le mode intégré; vous pouvez donc changer le comportement en définissant un local appelé dict par exemple, bien que je puisse pas penser à n'importe où cela serait une bonne idée en dehors de peut-être lors du débogage

107
John La Rooy

Le littéral est beaucoup plus rapide puisqu'il utilise les opcodes optimisés BUILD_MAP et STORE_MAP plutôt que les codes génériques CALL_FUNCTION:

> python2.7 -m timeit "d = dict(a=1, b=2, c=3, d=4, e=5)"
1000000 loops, best of 3: 0.958 usec per loop

> python2.7 -m timeit "d = {'a':1, 'b':2, 'c':3, 'd':4, 'e':5}"
1000000 loops, best of 3: 0.479 usec per loop

> python3.2 -m timeit "d = dict(a=1, b=2, c=3, d=4, e=5)"
1000000 loops, best of 3: 0.975 usec per loop

> python3.2 -m timeit "d = {'a':1, 'b':2, 'c':3, 'd':4, 'e':5}"
1000000 loops, best of 3: 0.409 usec per loop
51
Daniel Kluev

Ils se ressemblent beaucoup sur Python 3.2.

Comme l'a souligné gnibbler, le premier n'a pas besoin de rechercher dict, ce qui devrait le rendre un peu plus rapide.

>>> def literal():
...   d = {'one': 1, 'two': 2}
...
>>> def constructor():
...   d = dict(one='1', two='2')
...
>>> import dis
>>> dis.dis(literal)
  2           0 BUILD_MAP                2
              3 LOAD_CONST               1 (1)
              6 LOAD_CONST               2 ('one')
              9 STORE_MAP
             10 LOAD_CONST               3 (2)
             13 LOAD_CONST               4 ('two')
             16 STORE_MAP
             17 STORE_FAST               0 (d)
             20 LOAD_CONST               0 (None)
             23 RETURN_VALUE
>>> dis.dis(constructor)
  2           0 LOAD_GLOBAL              0 (dict)
              3 LOAD_CONST               1 ('one')
              6 LOAD_CONST               2 ('1')
              9 LOAD_CONST               3 ('two')
             12 LOAD_CONST               4 ('2')
             15 CALL_FUNCTION          512
             18 STORE_FAST               0 (d)
             21 LOAD_CONST               0 (None)
             24 RETURN_VALUE
38
Paolo Moretti

Ces deux approches produisent des dictionnaires identiques, sauf, comme vous l'avez noté, où les règles lexicales de Python interfèrent.

Les littéraux de dictionnaire sont un peu plus manifestement des dictionnaires, et vous pouvez créer n’importe quel type de clé, mais vous devez citer les noms de clé. D'autre part, vous pouvez utiliser des variables pour les clés si vous avez besoin pour une raison quelconque:

a = "hello"
d = {
    a: 'hi'
    }

Le constructeur dict() vous offre davantage de flexibilité en raison de la diversité des formes de saisie utilisées. Par exemple, vous pouvez lui fournir un itérateur de paires et il les traitera comme des paires clé/valeur.

Je ne sais pas pourquoi PyCharm proposerait de convertir un formulaire en un autre.

13
Ned Batchelder

Une grosse différence avec python 3.4 + pycharm est que le constructeur dict () génère un message "d'erreur de syntaxe" si le nombre de clés dépasse 256.

Je préfère utiliser le dict littéral maintenant.

7
Michel

De python 2.7 tutoriel:

Une paire d'accolades crée un dictionnaire vide: {}. Le fait de placer une liste de paires clé: valeur séparées par des virgules dans les accolades ajoute les paires clé: valeur au dictionnaire; c'est également ainsi que les dictionnaires sont écrits en sortie.

tel = {'jack': 4098, 'sape': 4139}
data = {k:v for k,v in Zip(xrange(10), xrange(10,20))}

Tandis que:

Le constructeur dict () construit des dictionnaires directement à partir de listes de paires clé-valeur stockées sous forme de tuples. Lorsque les paires forment un motif, la compréhension de liste peut spécifier de manière compacte la liste de valeurs-clés.

tel = dict([('sape', 4139), ('guido', 4127), ('jack', 4098)]) {'sape': 4139, 'jack': 4098, 'guido': 4127}
data = dict((k,v) for k,v in Zip(xrange(10), xrange(10,20)))

Lorsque les clés sont de simples chaînes, il est parfois plus facile de spécifier des paires à l'aide d'arguments de mots clés:

dict(sape=4139, guido=4127, jack=4098)
>>>  {'sape': 4139, 'jack':4098, 'guido': 4127}

Ainsi, {} et dict () produisent tous les deux un dictionnaire mais fournissent des manières légèrement différentes d’initialisation des données du dictionnaire.

6
Artsiom Rudzenka

Je trouve le littéral dict d = {'one': '1'} beaucoup plus lisible, vos données de définition, plutôt que d’assigner des valeurs et de les envoyer au constructeur dict().

D'un autre côté, j'ai vu des gens écrire mal le littéral dict comme d = {'one', '1'} qui, dans la version moderne python 2.7+, créera un ensemble.

Malgré cela, je préfère toujours utiliser le littéral d'ensemble, car je pense que sa préférence est plus lisible et personnelle, je suppose.

2
lee penkman

Il n'existe pas de littéral dict pour créer des classes dict-héritées, des classes dict personnalisées avec des méthodes supplémentaires. Dans ce cas, le constructeur de classe dict personnalisé doit être utilisé, par exemple:

class NestedDict(dict):

    # ... skipped

state_type_map = NestedDict(**{
    'owns': 'Another',
    'uses': 'Another',
})
2
Dmitriy Sintsov

le littéral dict () est Nice lorsque vous copiez en collant des valeurs à partir de quelque chose d'autre (aucun python). Par exemple, une liste de variables d'environnement. si vous aviez un fichier bash, dites

FOO='bar'
CABBAGE='good'

vous pouvez facilement coller ensuite dans un littéral dict() et ajouter des commentaires. Il est également plus facile de faire le contraire, de copier dans autre chose. Alors que la syntaxe {'FOO': 'bar'} est assez unique pour python et json. Donc, si vous utilisez beaucoup json, vous voudrez peut-être utiliser les littéraux {} avec des guillemets doubles.

0
Nick Humrich

Tenez également compte du fait que les jetons correspondant aux opérateurs ne peuvent pas être utilisés dans la syntaxe du constructeur, c'est-à-dire les clés dasherisées.

>>> dict(foo-bar=1)
File "<stdin>", line 1
SyntaxError: keyword can't be an expression

>>> {'foo-bar': 1}
{'foo-bar': 1}
0
Brian Whitton