web-dev-qa-db-fra.com

fonction any () en Python avec un rappel

La bibliothèque standard Python définit une fonction any() qui

Renvoie True si l'un des éléments de l'itérable est true. Si l'itérable est vide, retournez False.

Il vérifie uniquement si les éléments sont évalués à True. Ce que je veux, c'est pouvoir ainsi spécifier un rappel pour dire si un élément convient à la facture comme:

any([1, 2, 'joe'], lambda e: isinstance(e, int) and e > 0)
54
Emil Ivanov

Que diriez-vous:

>>> any(isinstance(e, int) and e > 0 for e in [1,2,'joe'])
True

Cela fonctionne aussi avec all() bien sûr:

>>> all(isinstance(e, int) and e > 0 for e in [1,2,'joe'])
False
99
Antoine P.

La fonction any renvoie True lorsque l'une des conditions est True.

>>> any(isinstance(e, int) and e > 0 for e in [0 ,0, 1])
True # Returns True because 1 is greater than 0.


>>> any(isinstance(e, int) and e > 0 for e in [0 ,0, 0])
False # Returns False because not a single condition is True.

En fait, le concept de la fonction any provient de LISP ou de l’approche de programmation par fonctions. Il y a une autre fonction qui est juste en face d'elle all

>>> all(isinstance(e, int) and e > 0 for e in [1, 33, 22])
True # Returns True when all the condition satisfies.

>>> all(isinstance(e, int) and e > 0 for e in [1, 0, 1])
False # Returns False when a single condition fails.

Ces deux fonctions sont vraiment chouettes lorsqu'elles sont utilisées correctement.

19
aatifh

Vous devez utiliser une "expression de générateur", c'est-à-dire une construction de langage pouvant consommer des itérateurs et appliquer un filtre et des expressions sur une seule ligne:

Par exemple, (i ** 2 for i in xrange(10)) est un générateur pour le carré des 10 premiers nombres naturels (0 à 9)

Ils permettent également à une clause "if" de filtrer les informations sur la clause "pour", ainsi, pour votre exemple, vous pouvez utiliser:

any (e for e in [1, 2, 'joe'] if isinstance(e, int) and e > 0)
7
jsbueno

Légère amélioration de la réponse d'Antoine P.

>>> any(type(e) is int for e in [1,2,'joe'])
True

Pour all()

>>> all(type(e) is int for e in [1,2,'joe'])
False
6
SohamC

Tandis que les autres donnaient de bonnes réponses Pythonic (je n'utiliserais que la réponse acceptée dans la plupart des cas), je voulais simplement souligner combien il est facile de créer votre propre fonction utilitaire pour le faire vous-même si vous le préférez vraiment:

def any_lambda(iterable, function):
  return any(function(i) for i in iterable)

In [1]: any_lambda([1, 2, 'joe'], lambda e: isinstance(e, int) and e > 0
Out[1]: True
In [2]: any_lambda([-1, '2', 'joe'], lambda e: isinstance(e, int) and e > 0)
Out[2]: False

Je pense au moins que je le définirais d'abord avec le paramètre function, car cela correspondrait plus étroitement aux fonctions intégrées existantes telles que map () et filter ():

def any_lambda(function, iterable):
  return any(function(i) for i in iterable)
5
ShawnFumo

le filtre peut fonctionner, en plus il vous renvoie les éléments correspondants

>>> filter(lambda e: isinstance(e, int) and e > 0, [1,2,'joe'])
[1, 2]
2
thanos

Vous pouvez utiliser une combinaison de any et map si vous voulez vraiment conserver votre notation lambda comme suit:

any(map(lambda e: isinstance(e, int) and e > 0, [1, 2, 'joe']))

Mais il est préférable d’utiliser une expression génératrice car elle ne construira pas la liste complète deux fois.

2
volent

Si vous vraiment voulez insérer un lambda dans un (), vous pouvez le faire: 

>>> any((lambda: isinstance(e, int))() for e in [1,2,'joe'])
True
>>> any((lambda: isinstance(e, int))() for e in ['joe'])
False

Il vous suffit de terminer le lambda non nommé et de vous assurer qu'il est invoqué à chaque passe en ajoutant le ()

L’avantage ici est que vous continuez à profiter du court-circuit de l’évaluation de tout résultat lorsque vous frappez le premier int

0
Doug Coburn