2009-05-11 22 views
7

Supponiamo Ho due dicts in Python:C'è un modo per impostare più valori predefiniti su un dict Python usando un altro dict?

mydict = { 'a': 0 } 

defaults = { 
    'a': 5, 
    'b': 10, 
    'c': 15 
} 

Voglio essere in grado di espandere mydict utilizzando i valori di default da defaults, in modo tale che 'a' rimane la stessa, ma 'b' e 'c' sono compilati. So di dict.setdefault() e di dict.update(), ma ognuno di essi fa solo la metà di quello che voglio: con dict.setdefault(), devo eseguire il loop su ciascuna variabile in defaults; ma con dict.update(), defaults eliminerà i valori preesistenti in mydict.

C'è qualche funzionalità che non trovo integrata in Python che possa fare questo? E se no, c'è un modo più Pythonic di scrivere un ciclo per chiamare ripetutamente dict.setdefaults() di questo:

for key in defaults.keys(): 
    mydict.setdefault(key, defaults[key]) 

Contesto: Sto scrivendo alcuni dati in Python che controlla come analizzare un albero XML. C'è un dict per ogni nodo (ad esempio, come elaborare ciascun nodo), e preferisco che i dati che scrivo siano sparsi, ma riempiti con valori predefiniti. Il codice di esempio è solo un esempio ... il codice reale ha molte più coppie chiave/valore nella dict predefinita.

(mi rendo conto tutta questa domanda è, ma una sottigliezza, ma sono io tormenta, quindi mi chiedevo se ci fosse un modo migliore per fare questo che io non sono a conoscenza.)

risposta

7

Non potresti rendere mydict una copia di default, in questo modo mydict avrebbe tutti i valori corretti per iniziare?

mydict = default.copy() 
+0

Sì, questo è quello che faccio anche io di solito .. – Macke

+0

Ho pensato a questo, ma non copiare le impostazioni predefinite è piuttosto inefficiente (specialmente mydict ha tutti i valori impostati per cominciare)? Dovresti creare un nuovo dettato, copiare tutti i valori di un altro, quindi riscrivere l'intero dettato in quel caso. –

+2

@Daniel Lew: i valori non verranno copiati, solo riferimenti a loro. Il nuovo dict avrà nuovi riferimenti agli stessi valori in memoria. – nosklo

0
defaults.update(mydict) 
+0

Quindi come potrò applicare le mie impostazioni predefinite a un altro nodo? –

+0

conserva una copia dell'originale da qualche parte. – SilentGhost

+0

Prima dovresti fare una copia di default, quindi ... – Stephan202

3

Se non ti dispiace la creazione di un nuovo dizionario nel processo, questo farà il trucco:

newdict = dict(defaults) 
newdict.update(mydict) 

Ora newdict contiene quello che ti serve.

5

È possibile farlo allo stesso modo collections.DefaultDict di Python funziona:

class MultiDefaultDict(dict): 
    def __init__(self, defaults, **kwargs): 
     self.defaults = defaults 
     self.update(kwargs) 
    def __missing__(self, key): 
     return self.defaults[key] 

>>> mydict2 = MultiDefaultDict(defaults, a=0) 
>>> mydict2['a'] 
0 
>>> mydict2['b'] 
10 
>>> mydict2 
{'a': 0} 

Le altre soluzioni postato finora duplicare tutti i valori di default; questo li condivide, come richiesto. Potresti o non vorresti sovrascrivere altri metodi dict come __taintains __(), __iter __(), items(), keys(), values ​​() - questa classe come definita qui esegue iterazioni solo sugli elementi non predefiniti.

+0

+1 Vale anche la pena sottolineare che a differenza di 'defaultdict' (e' setdefault() ') le eventuali chiavi mancanti e i valori predefiniti associati sono * not * effettivamente aggiunti al dizionario sottostante - che può essere o non essere desiderabile. In ogni caso, ovviamente, potrebbe essere cambiato ... – martineau

0

Personalmente mi piace aggiungere l'oggetto dizionario. Funziona principalmente come un dizionario, tranne per il fatto che devi prima creare l'oggetto.

class d_dict(dict): 
    'Dictionary object with easy defaults.' 
    def __init__(self,defaults={}): 
     self.setdefault(defaults)   
    def setdefault(self,defaults): 
     for key, value in defaults.iteritems(): 
      if not key in self: 
       dict.__setitem__(self,key,value) 

Questo fornisce la stessa funzionalità del tipo dict tranne che sostituisce il metodo setdefault() e richiederà un dizionario contenente uno o più articoli. È possibile impostare i valori predefiniti al momento della creazione.

Questa è solo una preferenza personale. Come ho capito tutto ciò che dict.setdefault() fa è impostare gli elementi che non sono stati ancora impostati. Quindi probabilmente il più semplice opzione di posto in è:

new_dict = default_dict.copy() 
new_dict.update({'a':0}) 

Tuttavia, se si esegue questa operazione più di una volta si potrebbe fare una funzione di questo.A questo punto potrebbe essere più semplice usare un oggetto dict personalizzato, piuttosto che aggiungere costantemente i valori predefiniti ai dizionari.

Problemi correlati