Em relação às respostas de @Hugh Bothwell, @mortehu e @glglgl.
Conjunto de dados de configuração para teste
import random
dataset = [random.randint(0,15) if random.random() > .6 else None for i in range(1000)]
Definir implementações
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)
Faça a função de teste
def test_func(dataset, func):
default = 1
for i in dataset:
func(i, default)
Resultados no mac i7 @ 2.7Ghz 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
Claramente o not_none
função responde à pergunta do OP corretamente e lida com o problema de "falsidade". É também o mais rápido e fácil de ler. Se aplicar a lógica em muitos lugares, é claramente o melhor caminho a percorrer.
Se você tiver um problema em que deseja encontrar o 1º valor não nulo em uma iterável, a resposta do @ mortehu é o caminho a percorrer. Mas é uma solução para um problema diferente do OP, embora possa lidar parcialmente com esse caso. Não pode levar um AND iterável e um valor padrão. O último argumento seria o valor padrão retornado, mas você não passaria um iterável nesse caso, assim como não está explícito que o último argumento seja o valor padrão.
Você poderia fazer isso abaixo, mas eu ainda usaria not_null
para o caso de uso de valor único.
def coalesce(*args, **kwargs):
default = kwargs.get('default')
return next((a for a in arg if a is not None), default)
??
operador é proposto como PEP 505 .