2012-12-31 14 views
20

Sono abbastanza conosco ternario approccio operatore di Python:Compressione `x se x il resto y` dichiarazione in Python

value = foo if something else bar 

La mia domanda è molto semplice: senza assegnazioni precedenti, c'è comunque di fare riferimento al termine dell'essere valutato in (if ...) da uno degli operandi di ritorno (... if o else ...)?

La motivazione qui è che a volte uso espressioni in if ... che sono esattamente ciò che mi piacerebbe avere come risultato nell'operazione ternaria; succede però che, per le piccole espressioni, non c'è problema a ripeterlo, ma per espressioni un po 'più lunghe, diventa un po' sgradevole. Prendi questo esempio:

value = info.findNext("b") if info.findNext("b") else "Oompa Loompa" 
+0

beh, Oompa Loompa è divertente! –

+0

@AspiringAqib non abbiamo il compito, ma possiamo ancora godere di alcune oompa loompas (: – Rubens

+0

beh, hai la soluzione laggiù eh? –

risposta

23

Non c'è modo di farlo, ed è intenzionale. Il ternario dovrebbe essere usato solo per casi banali.

Se si desidera utilizzare il risultato di un calcolo due volte, metterlo in una variabile temporanea:

value = info.findNext("b") 
value = value if value else "Oompa Loompa" 

Una volta fatto questo, è chiaro che si sta facendo qualcosa di sciocco, e infatti la modo divinatorio per scrivere questo è:

value = info.findNext("b") 
if not value: 
    value = "Oompa Loompa" 

E questo è in realtà 5 meno sequenze di tasti che il vostro tentativo originale.

Se davvero desidera salvare sequenze di tasti, si può invece fare questo:

value = info.findNext("b") or "Oompa Loompa" 

Ma questo è scoraggiato da molte guide di stile, e dal BDFL.

Se lo fai solo una volta, è meglio essere più esplicito. Se stai facendo una mezza dozzina di volte, è banale, e molto meglio da fare findNext prendere un opzionale per segnalare invece di None, proprio come tutte quelle funzioni built-in e stdlib:

def findNext(self, needle, defvalue=None): 
    # same code as before, but instead of return None or falling off the end, 
    # just return defvalue. 

Poi puoi fare questo:

value = info.findNext("b", "Oompa Loompa") 
+0

In realtà ho alcuni tic curiosi con la programmazione: non mi piace scrivere più di 70 colonne e apprezzo molto le soluzioni a una linea; il problema qui riguarda piuttosto la compattezza del numero esplicito di parole. Sto accettando la tua risposta, però, dato che stai rispondendo a un "sì/no" alla mia domanda binaria. Accettando, nondimeno, che l'utilizzo o, come indicato da @Ignacio, sia in assoluto la soluzione migliore. – Rubens

+0

Il ritorno di 'None' equivale a restituire 'null', e quindi [altrettanto grave] (http://en.wikipedia.org/wiki/Void_safety). –

+1

@Rubens: il modo pietonico per scrivere soluzioni a una sola riga è di concludere qualsiasi cosa complicata in una funzione esplicita. Se puoi aggiungere un 'defval' a' findNext', fallo; se non puoi, scrivi un involucro. Lingue diverse hanno stili idiomatici differenti (ad esempio, in Haskell, nominare una funzione che chiamerai solo una volta è l'odore del codice), e linguaggi diversi aderiscono ai loro idiomi in modo più deciso (es., In perl, "C'è solo un modo per farlo "sarebbe considerato un bug, non una funzionalità). Ma se hai scelto Python, dovresti imparare Python idiomatico. – abarnert

20

Non utilizzare affatto if ... else. Invece, approfitta degli operatori coalescenti di Python.

value = info.findNext("b") or "Oompa Loompa" 
+1

È [certamente un collegamento] (http: // docs.python.org/2/library/stdtypes.html#boolean-operations-and-or-not), @Rubens. 'x o y' dovrebbe essere compilato nello stesso codice di' if bool (x) then x else y'. 'bool' chiama' .__ nonzero __() '. –

+1

È _can_ fare questo, ma ciò non significa che si debba _should_. Se lo fai abbastanza volte che è necessario salvare 5 tasti, modifica il metodo 'findNext' per ottenere un valore predefinito. Altrimenti, scrivilo esplicitamente. – abarnert