Qual è la sintassi preferita per inizializzare un dict: letteral parentesi graffa {} o la funzione dict ()?


212

Mi sto impegnando per imparare Python e sto prestando molta attenzione agli standard di codifica comuni. Questa può sembrare una domanda inutilmente schizzinosa, ma sto provando a concentrarmi sulle migliori pratiche mentre imparo, quindi non devo disimparare alcuna "cattiva" abitudine.

Vedo due metodi comuni per inizializzare un dict:

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

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

Quale è considerato "più pitonico"? Quale usi? Perché?


5
Quale tutorial stai usando? Dove hai visto esempi che portano alla confusione?
S.Lott,

2
Bene, sto usando il tutorial di Python, Immergiti in Python e poi una varietà di blog, post SO e altre risorse su Google. I documenti ufficiali usano {}abbastanza uniformemente, ma vedo molto l' dict()approccio esplicito altrove. Ho potuto vedere il vantaggio di una sintassi esplicita, ma l'assenza dell'approccio nei documenti ufficiali mi ha reso sospettoso. Dopo aver pubblicato questo, ho esaminato i documenti della libreria dicte ho scoperto che le chiavi devono essere identificatori validi quando dictviene utilizzato un esplicito per inizializzare un dict.
daotoad,

2
In che modo "dict ()" è più esplicito di "{}"? Non capisco la tua confusione. Entrambi mi sembrano espliciti. Puoi fornire un preventivo o un riferimento che ti faccia dire che "dict" è "esplicito" e "{}" non è esplicito? Da dove pensi sia nata questa distinzione?
S.Lott

21
La distinzione è l'ortografia. dict()è scritto dict- utilizza il nome del tipo. Le parentesi graffe ( {}) si basano sulla punteggiatura per identificare il tipo.
daotoad,

Risposte:


235

Parentesi graffe. Passare argomenti per parole chiave dict(), sebbene funzioni magnificamente in molti scenari, può inizializzare una mappa solo se le chiavi sono identificatori Python validi.

Questo funziona:

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

Questo non funzionerà:

a =                  dict(import='trade', 1=7.8)
>> SyntaxError: invalid syntax  ^

85

Le prime parentesi graffe. In caso contrario, si verificano problemi di coerenza con chiavi che contengono caratteri dispari, ad esempio =.

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

# Eeep! Breaks if trying to be consistent.
b = dict( 
    a='value',
    b=c='value',
)

11
Questo è esattamente il motivo per cui si potrebbe preferire il metodo dict () per l'inizializzazione, impone che le chiavi del dizionario siano identificatori validi, quindi sono compatibili, ad esempio, con ** kwargs e le chiavi sono nomi di attributi validi.
RufusVS

57

La prima versione è preferibile:

  • Funziona con tutti i tipi di chiavi, quindi puoi, per esempio, dire {1: 'one', 2: 'two'}. La seconda variante funziona solo per (alcune) chiavi di stringa. L'uso di diversi tipi di sintassi a seconda del tipo di chiavi sarebbe un'incoerenza non necessaria.
  • È più veloce:

    $ 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 la sintassi speciale per i letterali del dizionario non fosse progettata per essere utilizzata, probabilmente non esisterebbe.

3

Penso che la prima opzione sia migliore perché accederai ai valori come ['a'] o [[altro ']. Le chiavi del tuo dizionario sono stringhe e non c'è motivo di fingere che non lo siano. Per me la sintassi delle parole chiave all'inizio sembra intelligente, ma oscura a un secondo sguardo. Questo ha senso per me solo se stai lavorando __dict__e le parole chiave diventeranno attributi in seguito, qualcosa del genere.


3

Cordiali saluti, nel caso in cui sia necessario aggiungere attributi al dizionario (elementi collegati al dizionario, ma non sono una delle chiavi), sarà necessario il secondo modulo. In tal caso, puoi inizializzare il dizionario con chiavi con caratteri arbitrari, uno alla volta, in questo modo:

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

2

A volte dict()è una buona scelta:

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) per x nell'intervallo (0,7)]))


2
Esiste una funzione enumerata che potrebbe fare meglio. Del resto, esiste un tipo Enum che può fare meglio quello che stai facendo qui. Inoltre, questa non è affatto una risposta alla domanda.
dusktreader,

2

Uso quasi sempre parentesi graffe; tuttavia, in alcuni casi in cui sto scrivendo test, eseguo il packaging / unpacking di parole chiave e in questi casi dict () è molto più gestibile, poiché non ho bisogno di cambiare:

a=1,
b=2,

per:

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

Aiuta anche in alcune circostanze in cui penso che potrei voler trasformarlo in un'istanza denominata coppia o classe in un secondo momento.

Nell'implementazione stessa, a causa della mia ossessione per l'ottimizzazione, e quando non vedo un beneficio di manutenibilità particolarmente grande, prediligo sempre le parentesi graffe.

Nei test e nell'implementazione, non userei mai dict () se c'è la possibilità che le chiavi aggiunte in quel momento, o in futuro, potrebbero:

  • Non essere sempre una stringa
  • Non contengono solo cifre, lettere ASCII e caratteri di sottolineatura
  • Inizia con un numero intero ( dict(1foo=2)genera un SyntaxError)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.