Cours
Un besoin fréquent dans les programmes Python est de vérifier si au moins un élément d’une structure de données vaut True.
Bien qu’il soit possible d’écrire une boucle pour parcourir un itérable et vérifier si chaque élément s’évalue à True ou False, la fonction any() de Python est une manière plus efficace et plus pythonique d’obtenir ce résultat.
Ce tutoriel explore la fonction intégrée any() de Python et présente plusieurs exemples et cas d’usage.
L'amélioration de l'IA pour les débutants
À quoi sert la fonction any() de Python ?
La fonction intégrée any() fait partie des built-ins. Elle accepte un itérable (par exemple une liste ou un tuple), et renvoie True si au moins une valeur de l’itérable est truthy. Une valeur « truthy » s’évalue à True lorsqu’on la convertit en booléen avec bool(). Si toutes les valeurs de l’itérable sont « falsy », any() renvoie False :
print(any([True, False, False, True]))
print(any([False, False, False, False]))
print(any([0, 0, 5, 0]))
True
False
True
L’itérable peut contenir des booléens ou d’autres objets, puisque tous les objets s’évaluent en True ou False dans un contexte booléen. Dans le troisième exemple, la liste contient quatre entiers. L’entier 0 est « falsy », mais tout nombre non nul est « truthy ». Pour mieux comprendre la différence entre valeurs « truthy » et « falsy », consultez cet article sur les opérateurs logiques en Python.
Si l’itérable est vide, any() renvoie False puisqu’il n’existe aucune valeur « truthy » dans un itérable vide :
print(any([]))
False
La section suivante détaille le fonctionnement de any().
Comment fonctionne any() ?
La fonction intégrée any() accepte n’importe quel itérable en argument. Un itérable est toute structure de données que Python peut parcourir.
Considérez le tuple suivant :
an_iterable = ("", 0.0, "DataCamp", False, [])
Ce tuple contient plusieurs objets de types différents. Plusieurs de ces objets sont « falsy » :
- La chaîne vide
"" - Le flottant
0.0 - Le booléen
False - La liste vide
[]
Ces objets sont « falsy » car ils s’évaluent à False lorsqu’on les passe à bool().
La chaîne non vide "DataCamp" est « truthy ».
Une façon simple de vérifier si au moins un élément est « truthy » consiste à utiliser une boucle for :
def check_if_contains_truthy(data):
output = False
for item in data:
if item:
output = True
return output
print(check_if_contains_truthy(an_iterable))
True
Cependant, cela manque d’efficacité puisque la fonction n’a besoin que de vérifier l’existence d’au moins une valeur « truthy ». Dès qu’elle en trouve une, elle n’a plus besoin de parcourir le reste de l’itérable. On peut modifier la fonction pour renvoyer un résultat dès la première valeur « truthy » trouvée :
def check_if_contains_truthy(data):
for item in data:
if item:
return True
return False
print(check_if_contains_truthy(an_iterable))
True
Une instruction return interrompt l’exécution de la fonction. Ainsi, lorsque la fonction trouve la première valeur « truthy », elle renvoie True et n’itère pas davantage. La fonction ne renvoie False que si la boucle for a parcouru tous les éléments sans en trouver un seul « truthy ».
La fonction intégrée any() suit le même principe et « court-circuite » dès la première valeur « truthy ». Cette évaluation paresseuse évite des opérations inutiles et améliore les performances. La version intégrée any() est donc plus efficace que la fonction maison ci-dessus. On peut le confirmer avec timeit() du module timeit, qui mesure le temps d’exécution d’une instruction :
from timeit import timeit
print("Execution time for 'check_if_contains_truthy()'")
print(
timeit(
"check_if_contains_truthy(an_iterable)",
number=10_000_000,
globals=globals(),
)
)
print("Execution time for 'any()'")
print(
timeit(
"any(an_iterable)",
number=10_000_000,
globals=globals(),
)
)
Execution time for 'check_if_contains_truthy()'
0.6335119580035098
Execution time for 'any()'
0.39488654200249584
Le premier argument de timeit() est une chaîne contenant l’instruction à exécuter. Le second précise le nombre d’exécutions. Ici, les deux instructions sont lancées 10 000 000 fois pour obtenir des mesures significatives. Le dernier argument transmet les variables globales à timeit().
La fonction any() est plus rapide que check_if_contains_truthy(). Utiliser any() pour savoir si un itérable contient au moins une valeur « truthy » est plus pythonique et plus performant qu’une boucle for.
Cas d’usage de any()
Voyons quelques cas d’usage de any() en Python.
Vérifier si au moins une saisie utilisateur est valide
Considérez une série de saisies utilisateur collectées dans une liste ou un tuple. Un programme peut avoir besoin de vérifier si au moins une saisie est valide, par exemple si c’est une chaîne non vide :
user_inputs = ["", "10.99", ""]
if any(user_inputs):
print("At least one valid input present")
# Rest of code...
else:
print("There are no valid inputs")
At least one valid input present
Comme l’une des chaînes n’est pas vide, any() renvoie True et le code du bloc if s’exécute.
Vérifier si au moins un fichier existe
La fonction intégrée any() peut servir à vérifier si au moins un des fichiers d’une liste existe dans un répertoire :
from pathlib import Path
files = ["article.md", "use_any.py", "scratch.py", "test_file.txt"]
cwd = Path.cwd()
# Create a test file to test code
Path("test_file.txt").write_text("This is a test file")
if any(Path(file).exists() for file in files):
print("At least one of the files exists")
# Rest of code…
else:
print("None of the files exist")
At least one of the files exists
Le code récupère le répertoire de travail courant via le module pathlib et Path.cwd(). Il crée un fichier nommé test_file.txt dans ce répertoire afin de pouvoir tester facilement le code. La fonction any() est ensuite utilisée pour vérifier si au moins un des noms de fichiers existe dans le répertoire courant.
Filtrer des éléments d’un itérable
La fonction intégrée any() peut aussi s’utiliser avec une expression génératrice en argument pour filtrer des éléments d’un itérable. Dans cet exemple, any() cherche au moins une entrée, dans une liste de dictionnaires représentant des personnes, dont l’âge est inférieur à 18 :
records = [
{"name": "Sarah", "age": 23},
{"name": "Jake", "age": 30},
{"name": "Paul", "age": 17},
]
if any(record["age"] < 18 for record in records):
print("There's at least one minor.")
else:
print("All records are adults.")
There's at least one minor.
L’expression génératrice renvoie True ou False selon la valeur associée à la clé "age" de chaque dictionnaire. Une expression génératrice est itérable, elle peut donc être passée à any().
Retour sur l’évaluation paresseuse de any() en Python
L’exemple précédent illustre aussi que any() évalue paresseusement. Considérez la modification suivante de la liste de dictionnaires :
records = [
{"name": "Sarah", "age": 23},
{"name": "Jake", "age": 30},
{"name": "Paul", "age": 17},
{"name": "Jill"},
]
if any(record["age"] < 18 for record in records):
print("There's at least one minor.")
else:
print("All records are adults.")
There's at least one minor.
Le quatrième dictionnaire de records ne contient pas la clé "age". Pourtant, le code ne lève pas d’erreur lors de l’accès à cette clé, car any() a déjà trouvé une valeur « truthy ». La fonction court-circuite dès qu’elle rencontre la première valeur « truthy ».
Le code lève un KeyError si le dictionnaire dépourvu de la clé "age" apparaît avant tout élément dont l’âge est inférieur à 18 :
records = [
{"name": "Jill"},
{"name": "Sarah", "age": 23},
{"name": "Jake", "age": 30},
{"name": "Paul", "age": 17},
]
if any(record["age"] < 18 for record in records):
print("There's at least one minor.")
else:
print("All records are adults.")
Traceback (most recent call last):
...
if any(record["age"] < 18 for record in records):
~~~~~^^^^^^
KeyError: 'age'
Cet exemple illustre le comportement de court-circuit avec any(). Il existe une alternative si vous ne souhaitez pas lever d’exception pour les éléments sans clé "age" : utiliser la méthode de dictionnaire .get() avec une valeur par défaut, plutôt qu’un accès via crochets. L’instruction if peut être remplacée par la version suivante si l’on considère par défaut que les entrées sans âge ne sont pas mineures :
if any(record.get("age", 18) < 18 for record in records):
# ...
Si le code doit considérer qu’une entrée sans âge est mineure, choisissez une valeur par défaut inférieure à 18.
Python : any() vs all()
La fonction any() a une fonction sœur, all(). Cette fonction intégrée accepte également un itérable et renvoie True si tous les éléments de l’itérable sont « truthy ».
Reprenons l’exemple de validation de saisies utilisateur vu plus haut. any() est utile si l’application exige au moins une saisie valide. En revanche, all() s’impose si toutes les saisies doivent être valides :
user_inputs = ["", "10.99", ""]
if any(user_inputs):
print("At least one valid input present")
# Rest of code...
else:
print("There are no valid inputs")
if all(user_inputs):
print("All inputs are valid")
# Rest of code...
else:
print("Not all inputs are valid")
At least one valid input present
Not all inputs are valid
Cependant, si toutes les chaînes des saisies utilisateur sont non vides, all() renvoie True :
user_inputs = ["5.99", "10.99", "19.99"]
# …
At least one valid input present
All inputs are valid
À l’instar de any(), all() évalue paresseusement et court-circuite dès la première valeur « falsy ».
Conclusion
La fonction any() détermine si au moins un élément d’un itérable est « truthy ». Elle renvoie True si au moins un élément vaut True ou s’évalue à True dans un contexte booléen. Même si l’on peut obtenir le même résultat avec une boucle, cette fonction intégrée offre une solution plus lisible et plus efficace.
Obtenez une certification de haut niveau en matière d'IA
J'ai étudié la physique et les mathématiques au niveau UG à l'université de Malte. J'ai ensuite déménagé à Londres et obtenu un doctorat en physique à l'Imperial College. J'ai travaillé sur de nouvelles techniques optiques pour obtenir des images de la rétine humaine. Aujourd'hui, je me concentre sur l'écriture, la communication et l'enseignement de Python.
