Per quanto riguarda le risposte di @Hugh Bothwell, @mortehu e @glglgl.
Imposta set di dati per i test
import random
dataset = [random.randint(0,15) if random.random() > .6 else None for i in range(1000)]
Definire le implementazioni
def not_none(x, y=None):
if x is None:
return y
return x
def coalesce1(*arg):
return reduce(lambda x, y: x if x is not None else y, arg)
def coalesce2(*args):
return next((i for i in args if i is not None), None)
Rendi la funzione di test
def test_func(dataset, func):
default = 1
for i in dataset:
func(i, default)
Risultati su Mac i7 a 2,7 Ghz usando Python 2.7
>>> %timeit test_func(dataset, not_none)
1000 loops, best of 3: 224 µs per loop
>>> %timeit test_func(dataset, coalesce1)
1000 loops, best of 3: 471 µs per loop
>>> %timeit test_func(dataset, coalesce2)
1000 loops, best of 3: 782 µs per loop
Chiaramente la not_none
funzione risponde correttamente alla domanda del PO e gestisce il problema "falsa". È anche il più veloce e facile da leggere. Se si applica la logica in molti luoghi, è chiaramente il modo migliore di procedere.
Se hai un problema in cui vuoi trovare il primo valore non nullo in un iterabile, allora la risposta di @ mortehu è la strada da percorrere. Ma è una soluzione a un problema diverso rispetto a OP, sebbene possa gestire parzialmente quel caso. Non può accettare un valore iterabile E un valore predefinito. L'ultimo argomento sarebbe il valore predefinito restituito, ma in questo caso non si passerà a un iterabile e non è esplicito che l'ultimo argomento sia un valore predefinito.
Potresti quindi fare di seguito, ma userei comunque not_null
per il caso d'uso a valore singolo.
def coalesce(*args, **kwargs):
default = kwargs.get('default')
return next((a for a in arg if a is not None), default)
??
operatore è proposto come PEP 505 .