¿Cuál es la sintaxis preferida para inicializar un dict: curly brace literals {} o la función dict ()?

212

Estoy haciendo un esfuerzo para aprender Python, y estoy prestando mucha atención a los estándares de codificación comunes. Esto puede parecer una pregunta inútilmente quisquillosa, pero estoy tratando de centrarme en las mejores prácticas a medida que aprendo, por lo que no tengo que desaprender ningún hábito "malo".

Veo dos métodos comunes para inicializar un dict:

a = {
    'a': 'value',
    'another': 'value',
}

b = dict( 
    a='value',
    another='value',
)

¿Cuál se considera "más pitónico"? Cual usas ¿Por qué?

daotoad
fuente
55
¿Qué tutorial estás usando? ¿Dónde viste ejemplos que conducen a la confusión?
S.Lott
2
Bueno, he estado usando el tutorial de Python, Sumérgete en Python y luego en una variedad de blogs, publicaciones SO y otros recursos en Google. Los documentos oficiales se usan de manera {}bastante uniforme, pero veo mucho del dict()enfoque explícito en otros lugares. Pude ver el beneficio de una sintaxis explícita, pero la ausencia del enfoque en los documentos oficiales me hizo sospechar. Después de publicar esto, miré los documentos de la biblioteca dicty encontré la advertencia de que las claves deben ser identificadores válidos cuando dictse usa un explícito para inicializar un dict.
Daotoad
2
¿Cómo es "dict ()" más explícito que "{}"? No entiendo tu confusión. Ambos me parecen explícitos. ¿Puede proporcionar una cita o referencia que le haga decir que "dict" es "explícito" y que "{}" no lo es? ¿De dónde crees que surgió esta distinción?
S.Lott
21
La distinción es la ortografía. dict()se deletrea, dictusa el nombre del tipo. Las llaves ( {}) se basan en la puntuación para identificar el tipo.
Daotoad

Respuestas:

235

Tirantes rizados. Al pasar argumentos de palabras clave dict(), aunque funciona muy bien en muchos escenarios, solo puede inicializar un mapa si las claves son identificadores válidos de Python.

Esto funciona:

a = {'import': 'trade', 1: 7.8}
a = dict({'import': 'trade', 1: 7.8})

Esto no funcionará:

a =                  dict(import='trade', 1=7.8)
>> SyntaxError: invalid syntax  ^
Wai Yip Tung
fuente
85

El primero, llaves. De lo contrario, tiene problemas de coherencia con las teclas que tienen caracteres extraños, como =.

# Works fine.
a = {
    'a': 'value',
    'b=c': 'value',
}

# Eeep! Breaks if trying to be consistent.
b = dict( 
    a='value',
    b=c='value',
)
Ámbar
fuente
11
Esto es exactamente por qué uno podría preferir el método dict () para la inicialización, obliga a las claves del diccionario a ser identificadores válidos, por lo que son compatibles con, por ejemplo, ** kwargs, y las claves son nombres de atributos válidos.
RufusVS
57

La primera versión es preferible:

  • Funciona para todo tipo de teclas, por lo que puede, por ejemplo, decir {1: 'one', 2: 'two'}. La segunda variante solo funciona para (algunas) teclas de cadena. Usar diferentes tipos de sintaxis dependiendo del tipo de las claves sería una inconsistencia innecesaria.
  • Es mas rapido:

    $ python -m timeit "dict(a='value', another='value')"
    1000000 loops, best of 3: 0.79 usec per loop
    $ python -m timeit "{'a': 'value','another': 'value'}"
    1000000 loops, best of 3: 0.305 usec per loop
    
  • Si la sintaxis especial para los literales del diccionario no fuera a usarse, probablemente no existiría.
stephan
fuente
3

Creo que la primera opción es mejor porque vas a acceder a los valores como ['a'] u ['otro']. Las claves en su diccionario son cadenas, y no hay razón para fingir que no lo son. Para mí, la sintaxis de palabras clave parece inteligente al principio, pero oscura en una segunda mirada. Esto solo tiene sentido para mí si está trabajando __dict__, y las palabras clave se convertirán en atributos más tarde, algo así.

dividir entre cero
fuente
3

Para su información, en caso de que necesite agregar atributos a su diccionario (cosas que están adjuntas al diccionario, pero no son una de las claves), necesitará la segunda forma. En ese caso, puede inicializar su diccionario con teclas que tengan caracteres arbitrarios, uno a la vez, de esta manera:

    class mydict(dict): pass
    a = mydict()        
    a["b=c"] = 'value'
    a.test = False
Joshua Richardson
fuente
2

A veces dict()es una buena opción:

a=dict(zip(['Mon','Tue','Wed','Thu','Fri'], [x for x in range(1, 6)]))

mydict=dict(zip(['mon','tue','wed','thu','fri','sat','sun'],

[random.randint (0,100) para x en el rango (0,7)]))

Deqing
fuente
2
Hay una función de enumeración que podría hacerlo mejor. Para el caso, hay un tipo Enum que puede hacer mejor lo que está haciendo aquí. Además, esta no es realmente una respuesta a la pregunta.
dusktreader
2

Casi siempre uso llaves; sin embargo, en algunos casos donde escribo pruebas, hago el empaquetado / desempaquetado de palabras clave, y en estos casos dict () es mucho más fácil de mantener, ya que no necesito cambiar:

a=1,
b=2,

a:

'a': 1,
'b': 2,

También ayuda en algunas circunstancias en las que creo que podría querer convertirlo en una instancia de clase o tupla con nombre más adelante.

En la implementación en sí, debido a mi obsesión por la optimización, y cuando no veo un beneficio de mantenimiento particularmente grande, siempre favoreceré las llaves.

En las pruebas y la implementación, nunca usaría dict () si existe la posibilidad de que las claves agregadas en ese momento, o en el futuro,:

  • No siempre ser una cuerda
  • No solo contiene dígitos, letras ASCII y guiones bajos
  • Comience con un número entero ( dict(1foo=2)genera un SyntaxError)
usuario989266
fuente