2011-10-07 16 views
5

Sto analizzando le richieste JSON utilizzando la libreria JSON che analizza nel dizionario python. Poiché le richieste sono generate dall'utente, devo correggere i valori predefiniti per i parametri che non sono stati forniti. Altre lingue hanno roba simile agli operatori ternari che hanno senso per le applicazioni ripetitive. Ma il codice seguente necessita di 4 righe per parametro.Come risolvere i valori di default da un dizionario Pythonico?

if "search_term" in request.keys(): 
    search_term=request['search_term'] 
else: 
    search_term="" 
if "start" in request.keys(): 
    start=request['start'] 
else: 
    start=0 
if "rows" in request.keys(): 
    rows=request['rows'] 
else: 
    rows=1000000 

Esiste un modo Pythonic per ridurre le righe di codice o renderlo più leggibile?


Edit: Sia la (in alto) le risposte sono ugualmente utili. Ho usato sia in circostanze diverse

+0

dato che nessun altro ha fatto notare ancora, la linea: ** se "righe" in request.keys(): ** è equivalente al più semplice: ** se "righe" nella richiesta: **. – MrWonderful

risposta

15

utilizzare il metodo dict.update su una copia delle impostazioni predefinite:

defaults = dict(a=1, b=2, c=3) 

result = dict(defaults) # Copy the defaults 
result.update(request) # Update with your values 

Questo consente di mantenere defaults come un attributo di classe o di variabile globale del modulo, che probabilmente si vuole fare.

È possibile anche combinare le ultime due righe in:

result = dict(defaults, **request) 

Per un'altra soluzione, vedere Kevin's answer.

+0

Mi piace come alternativa a dict.get(), perché consente di specificare tutti i valori predefiniti su una riga. Questo può essere utile se è probabile che i valori predefiniti cambino in futuro, quindi non è necessario cercare tra le istruzioni 'if' per trovare dove sono dichiarati. – Kevin

+0

+1: fornisce una posizione centrale per gestire i valori predefiniti e altamente mantenibile. Buona risposta! –

+2

+1. Questa è una soluzione eccellente. Devo sottolineare che con questo metodo bisogna usare una copia di "default", altrimenti "default" viene modificato. Inoltre, la logica non può essere capovolta. Facendo 'request.update (default)' sovrascriverà la richiesta con valori predefiniti. –

12

È possibile utilizzare il metodo dizionario get, il cui secondo argomento è il valore predefinito da restituire se non esiste alcun valore nel dizionario.

start = request.get('start', 0) 
+0

+1 Questo metodo è leggibile e semplice da comprendere. Lo preferisco quando non ci sono troppi valori con valori predefiniti. –

+1

vorrei poter accettare due risposte :-( – aitchnyu

2

Python dizionari hanno una funzione get() che prende un parametro di default (è possibile verificare che here). Così si può fare qualcosa di simile:

params.get('search_term', '') 
params.get('some_other_field', 0) 

e così via.

EDIT :: Probabilmente vuoi andare con la soluzione update di Petr sopra.

2

Se si ha la fortuna di utilizzare Python 3.3+, è possibile utilizzare collections.ChainMap:

from collections import ChainMap 

defaults = {'color': 'red', 'taste': 'sweet'} 
request = {'taste': 'sour', 'size': 'small'} 

result = ChainMap(request, defaults) 

print(result['taste']) # sour -- overridden 
print(result['color']) # red -- from default 
print(result['size']) # small -- new value 

Sia i defaults e request dicts sono “legati” al ChainMap, non copiato. Eventuali modifiche a loro si rifletteranno nel result:

defaults['color'] = 'green' 
print(result['color']) # green 

del result['taste'] 
print(result['taste']) # sweet 

Per evitare questo, è possibile convertire un ChainMap per dict quando hai finito costruirlo. Questo aiuta anche se avete bisogno di trattare con il codice arrogante che fa isinstance(result, dict):

print(dict(result)) 
# {'color': 'green', 'taste': 'sweet', 'size': 'small'} 
+0

Nice. C'è un'implementazione 2.x utilizzabile di ChainMap (scritto in modo leggermente diverso) all'indirizzo http://code.activestate.com/recipes/305268/ (il link è nella 3.x documenti ma ho pensato che dovrebbe andare anche qui.) – torek

+0

@torek Vero. Probabilmente non vale la pena il disturbo in questo caso particolare, però. –

Problemi correlati