Qual é a sintaxe preferida para inicializar um dict: literais entre chaves {} ou a função dict ()?

212

Estou fazendo algum esforço para aprender Python e prestando muita atenção aos padrões comuns de codificação. Isso pode parecer uma pergunta inútil, mas estou tentando me concentrar nas melhores práticas à medida que aprendo, para não precisar desaprender nenhum hábito "ruim".

Eu vejo dois métodos comuns para inicializar um ditado:

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

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

Qual é considerado "mais pitônico"? Qual você usa? Por quê?

daotoad
fonte
5
Que tutorial você está usando? Onde você viu exemplos que levaram à confusão?
S.Lott
2
Bem, eu tenho usado o tutorial do Python, Mergulhe no Python e, em seguida, uma variedade de blogs, publicações de SO e outros recursos do Google. Os documentos oficiais usam de maneira {}bastante uniforme, mas vejo muitas dict()abordagens explícitas em outros lugares. Pude ver o benefício de uma sintaxe explícita, mas a ausência da abordagem nos documentos oficiais me deixou desconfiada. Depois de postar isso, examinei os documentos da biblioteca dicte constatei o cuidado de que as chaves devem ser identificadores válidos quando um explícito dicté usado para inicializar um ditado.
daotoad
2
Como "dict ()" é mais explícito que "{}"? Eu não estou entendendo sua confusão. Ambos parecem explícitos para mim. Você pode fornecer uma cotação ou referência que diga "dict" é "explícito" e "{}" não é explícito? De onde você acha que essa distinção surgiu?
S.Lott
21
A distinção é ortografia. dict()está escrito dict- ele usa o nome do tipo. As chaves ( {}) dependem de pontuação para identificar o tipo.
daotoad

Respostas:

235

Aparelhos encaracolados. Passando argumentos de palavra-chave paradict() , embora funcione perfeitamente em muitos cenários, só pode inicializar um mapa se as chaves forem identificadores Python válidos.

Isso funciona:

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

Isso não vai funcionar:

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

O primeiro aparelho, encaracolado. Caso contrário, você terá problemas de consistência com chaves com caracteres estranhos, como =.

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

# Eeep! Breaks if trying to be consistent.
b = dict( 
    a='value',
    b=c='value',
)
Âmbar
fonte
11
É exatamente por isso que se pode preferir o método dict () para inicialização, obriga as chaves do dicionário a serem identificadores válidos, para que sejam compatíveis com, por exemplo, ** kwargs, e as chaves sejam nomes de atributos válidos.
RufusVS
57

A primeira versão é preferível:

  • Funciona para todos os tipos de chaves, para que você possa, por exemplo, dizer {1: 'one', 2: 'two'}. A segunda variante funciona apenas para (algumas) chaves de sequência. Usar diferentes tipos de sintaxe, dependendo do tipo das chaves, seria uma inconsistência desnecessária.
  • É mais rápido:

    $ 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
  • Se a sintaxe especial para literais de dicionário não fosse usada, provavelmente não existiria.
stephan
fonte
3

Eu acho que a primeira opção é melhor porque você acessará os valores como um ['a'] ou um ['another']. As chaves do seu dicionário são cadeias de caracteres e não há razão para fingir que não são. Para mim, a sintaxe da palavra-chave parece inteligente a princípio, mas obscura em uma segunda olhada. Isso só faz sentido para mim se você estiver trabalhando __dict__e as palavras-chave se tornarem atributos mais tarde, algo assim.

divida por zero
fonte
3

Para sua informação, caso você precise adicionar atributos ao seu dicionário (itens anexados ao dicionário, mas que não são uma das chaves), será necessário o segundo formulário. Nesse caso, você pode inicializar seu dicionário com chaves com caracteres arbitrários, um de cada vez, da seguinte forma:

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

Às vezes dict()é uma boa escolha:

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 no intervalo (0,7)]))

Deqing
fonte
2
Há uma função enumerada que poderia fazer isso melhor. Por falar nisso, existe um tipo de Enum que pode fazer melhor o que você está fazendo aqui. Além disso, isso não é realmente uma resposta para a pergunta.
dusktreader
2

Eu quase sempre uso suspensórios; no entanto, em alguns casos em que estou escrevendo testes, faço a compactação / descompactação de palavras-chave e, nesses casos, dict () é muito mais sustentável, pois não preciso alterar:

a=1,
b=2,

para:

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

Também ajuda em algumas circunstâncias em que acho que posso transformá-lo em uma instância nomeada de casal ou classe posteriormente.

Na implementação em si, devido à minha obsessão com a otimização, e quando não vejo um benefício particularmente grande de manutenção, sempre farei favor de chaves.

Nos testes e na implementação, eu nunca usaria dict () se houver uma chance de que as chaves adicionadas então, ou no futuro, sejam:

  • Nem sempre seja uma string
  • Não contêm apenas dígitos, letras ASCII e sublinhados
  • Comece com um número inteiro ( dict(1foo=2)gera um SyntaxError)
user989266
fonte