Respecto a las respuestas de @Hugh Bothwell, @mortehu y @glglgl.
Configurar el conjunto de datos para probar
import random
dataset = [random.randint(0,15) if random.random() > .6 else None for i in range(1000)]
Definir implementaciones
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)
Hacer la función de prueba
def test_func(dataset, func):
default = 1
for i in dataset:
func(i, default)
Resultados en 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 el not_none
función responde la pregunta del OP correctamente y maneja el problema de "falsedad". También es el más rápido y fácil de leer. Si aplica la lógica en muchos lugares, es claramente la mejor manera de hacerlo.
Si tiene un problema en el que desea encontrar el primer valor no nulo en un iterable, entonces la respuesta de @ mortehu es el camino a seguir. Pero es una solución a un problema diferente al OP, aunque puede manejar parcialmente ese caso. No puede tomar un valor iterativo Y predeterminado. El último argumento sería el valor predeterminado devuelto, pero entonces no pasaría un iterable en ese caso y no es explícito que el último argumento sea un valor predeterminado.
Podrías hacerlo a continuación, pero igual lo usaría not_null
para el 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 se propone como PEP 505 .