Concernant les réponses de @Hugh Bothwell, @mortehu et @glglgl.
Configuration du jeu de données pour les tests
import random
dataset = [random.randint(0,15) if random.random() > .6 else None for i in range(1000)]
Définir les implémentations
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)
Faire la fonction de test
def test_func(dataset, func):
default = 1
for i in dataset:
func(i, default)
Résultats sur Mac i7 @ 2.7Ghz en utilisant 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
De toute évidence, not_none
fonction répond correctement à la question de l'OP et gère le problème de "falsification". Il est également le plus rapide et le plus facile à lire. Si vous appliquez la logique à de nombreux endroits, c'est clairement la meilleure façon de procéder.
Si vous avez un problème où vous voulez trouver la 1ère valeur non nulle dans un itérable, alors la réponse de @ mortehu est la voie à suivre. Mais c'est une solution à un problème différent de celui de l'OP, bien qu'il puisse gérer partiellement ce cas. Il ne peut pas prendre une valeur itérable ET une valeur par défaut. Le dernier argument serait la valeur par défaut retournée, mais vous ne seriez pas en train de passer un itérable dans ce cas aussi bien qu'il n'est pas explicite que le dernier argument est une valeur par défaut.
Vous pouvez ensuite le faire ci-dessous, mais je l'utiliserais toujours not_null
pour le cas d'utilisation à valeur unique.
def coalesce(*args, **kwargs):
default = kwargs.get('default')
return next((a for a in arg if a is not None), default)
??
opérateur est proposé comme PEP 505 .