85 votes

fonction any() en Python avec un callback

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

Retourne Vrai si un élément de l'itérable est vrai. Si l'itérable est vide, il renvoie False.

Il vérifie seulement si les éléments sont évalués à True . Ce que je veux c'est pouvoir spécifier un callback pour dire si un élément correspond au projet, par exemple :

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

4 votes

Si vous voulez, vous pouvez toujours utiliser any(map(lambda:..., [...])) mais utiliser un générateur de compréhension est plus idiomatique.

139voto

Antoine P. Points 2212

Pourquoi pas :

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

Il fonctionne également avec all() bien sûr :

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

8 votes

Le problème de ce type de fonction n'est-il pas qu'elle va d'abord créer toute une liste de booléens et ensuite vérifier si l'un d'entre eux est vrai ? au lieu de s'arrêter après avoir trouvé la première instance valide ?

7 votes

@JoelHarkes Tant que vous n'encapsulez pas l'itérable dans [] o list() il devrait utiliser un générateur et fonctionner comme prévu.

20voto

Algunillo Points 33

cualquier La fonction renvoie Vrai lorsque n'importe quelle condition est Vrai.

>>> 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 cualquier La fonction est issue de Lisp ou, en d'autres termes, de l'approche de la programmation par fonctions. Il existe une autre fonction qui est juste opposée à celle-ci, à savoir todo

>>> 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 cool lorsqu'elles sont utilisées correctement.

13voto

jsbueno Points 22212

Vous devez utiliser une "expression génératrice", c'est-à-dire une construction du langage qui peut consommer des itérateurs et appliquer des filtres et des expressions sur ceux-ci 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" pour filtrer les itens sur la clause "for", donc pour votre exemple vous pouvez utiliser :

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

1 votes

Merci d'avoir mentionné le générateur, car je pense que c'est ce qui le rend le plus proche d'une version lambda (en termes de ne pas avoir à traiter la liste entière si un élément précédent est faux). Aussi, c'est bien de savoir qu'on peut laisser les parenthèses d'un générateur si c'est le seul paramètre. J'ai manqué ça

8voto

user1603970 Points 159

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

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

Para all()

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

6voto

ShawnFumo Points 445

Alors que les autres ont donné de bonnes réponses pythoniques (je me contenterais d'utiliser la réponse acceptée dans la plupart des cas), je voulais juste souligner combien il est facile de créer votre propre fonction utilitaire pour faire cela 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 que je la définirais au moins avec le paramètre fonction d'abord, car cela correspondrait mieux aux fonctions intégrées existantes comme map() et filter() :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X