Odnośnie odpowiedzi @Hugh Bothwell, @mortehu i @glglgl.
Skonfiguruj zestaw danych do testowania
import random
dataset = [random.randint(0,15) if random.random() > .6 else None for i in range(1000)]
Zdefiniuj implementacje
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)
Włącz funkcję testową
def test_func(dataset, func):
default = 1
for i in dataset:
func(i, default)
Wyniki na komputerze Mac i7 @ 2.7 Ghz przy użyciu języka 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
Oczywiście not_none
funkcja poprawnie odpowiada na pytanie OP i radzi sobie z problemem „falsy”. Jest to również najszybszy i najłatwiejszy do odczytania. Jeśli zastosujesz logikę w wielu miejscach, jest to zdecydowanie najlepsza droga.
Jeśli masz problem, w którym chcesz znaleźć pierwszą wartość inną niż null w iterowalnym, odpowiedź @ mortehu jest dobrym rozwiązaniem. Ale jest to rozwiązanie innego problemu niż OP, chociaż może częściowo poradzić sobie z tą sprawą. Nie może przyjąć iterowalnej ORAZ wartości domyślnej. Ostatnim argumentem byłaby zwrócona wartość domyślna, ale w takim przypadku nie przekazano by się iterowalnego, a także nie jest jasne, że ostatni argument jest wartością domyślną.
Możesz wtedy zrobić poniżej, ale nadal używałbym not_null
dla przypadku użycia pojedynczej wartości.
def coalesce(*args, **kwargs):
default = kwargs.get('default')
return next((a for a in arg if a is not None), default)
??
Operator zaproponowano PEP 505 .