50% off DataCamp Premium. 700+ courses, half price. Start learning today.
Een veelvoorkomende behoefte in Python-programma’s is controleren of minstens één element van een datastructuur True is.
Hoewel je een lus kunt schrijven om door een iterabele te lopen en te controleren of elk item naar True of False evalueert, is de Python-functie any() een efficiëntere en meer Pythonic manier om dit te bereiken.
Deze tutorial verkent de ingebouwde Python-functie any() en laat verschillende voorbeelden en use-cases voor deze functie zien.
Wat doet de any()-functie van Python?
Python's any() is een van de ingebouwde functies. Hij accepteert een iterable zoals een list of tuple, en hij geeft True terug als er minstens één truthy waarde in de iterable zit. Een truthy waarde wordt geëvalueerd als True wanneer deze met bool() naar een Booleaan wordt gecast. Als alle waarden in de iterable falsy zijn, retourneert any() False:
print(any([True, False, False, True]))
print(any([False, False, False, False]))
print(any([0, 0, 5, 0]))
True
False
True
De iterable kan Booleans of andere objecten bevatten, omdat alle objecten als True of False worden geëvalueerd wanneer ze naar een Booleaan worden gecast. In het derde voorbeeld bevat de lijst vier gehele getallen. Het gehele getal 0 is falsy, maar alle niet-nulgetallen zijn truthy. Lees deze blog over logische operatoren in Python om het verschil tussen truthy en falsy waarden beter te begrijpen.
Als de iterable leeg is, retourneert any() False omdat er geen truthy waarden in een lege iterable staan:
print(any([]))
False
De volgende sectie gaat dieper in op hoe any() werkt.
Hoe werkt any()?
De ingebouwde any() accepteert elke iterable als argument. Een iterable is elke datastructuur waar Python over kan itereren.
Bekijk de volgende tuple:
an_iterable = ("", 0.0, "DataCamp", False, [])
De tuple bevat meerdere objecten met verschillende types. Een aantal van deze objecten is falsy:
- De lege string
"" - De float
0.0 - De Boolean
False - De lege lijst
[]
Deze objecten zijn falsy omdat ze als False worden geëvalueerd wanneer ze aan bool() worden doorgegeven.
De niet-lege string "DataCamp" is truthy.
Een eenvoudige manier om te controleren of minstens één element truthy is, is met een for-lus:
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
Dit is echter inefficiënt, omdat de functie alleen hoeft te controleren of er minstens één truthy waarde is. Zodra een truthy waarde is gevonden, hoeft de rest van de items in de iterable niet meer te worden gecontroleerd. De functie kan worden aangepast om te retourneren zodra de eerste truthy waarde is gevonden:
def check_if_contains_truthy(data):
for item in data:
if item:
return True
return False
print(check_if_contains_truthy(an_iterable))
True
Een return-statement stopt de uitvoering van de functie. Daarom retourneert de functie True zodra de eerste truthy waarde is gevonden en gaat hij niet verder met itereren over de iterable. De functie retourneert alleen False als de for-lus alle items in de iterable doorloopt en geen daarvan truthy is.
De ingebouwde any() volgt een vergelijkbaar patroon en kortsluit zodra de eerste truthy waarde wordt gevonden. Deze luie evaluatie voorkomt onnodige bewerkingen, wat de prestaties verbetert. Python's any() is een efficiëntere versie van de bovenstaande functie. Deze hogere efficiëntie wordt bevestigd met de functie timeit() uit de module timeit, die meet hoelang Python erover doet om een statement uit te voeren:
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
Het eerste argument van de functie timeit() is een string met het uit te voeren statement. Het tweede argument bepaalt hoe vaak het statement moet worden uitgevoerd. In dit voorbeeld worden beide statements 10.000.000 keer uitgevoerd om betekenisvolle tijden te krijgen. Met het laatste argument worden de globale variabelen aan de functie timeit() doorgegeven.
Python's any() is sneller dan check_if_contains_truthy(). any() gebruiken om te bepalen of een iterable minstens één truthy waarde bevat, is Pythonischer en efficiënter dan een for-lus.
Use cases voor any()
Laten we enkele use cases voor Python's any() bekijken.
Controleren of minstens één gebruikersinvoer geldig is
Stel je een reeks gebruikersinvoer voor die in een lijst of tuple is verzameld. Een programma moet misschien controleren of minstens één van de invoeren geldig is, bijvoorbeeld als het een niet-lege string is:
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
Omdat één van de strings niet leeg is, retourneert any() True en wordt de code in de if-clausule uitgevoerd.
Controleren of minstens één bestand bestaat
De ingebouwde any() kan worden gebruikt om na te gaan of in een lijst met bestandsnamen minstens één bestand in een map bestaat:
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
De code haalt de huidige werkmap op met behulp van het pathlib-module en Path.cwd(). Er wordt een bestand test_file.txt in de werkmap gemaakt om ervoor te zorgen dat deze code eenvoudig getest kan worden. Python's any() wordt gebruikt om te controleren of er minstens één van de bestandsnamen in de huidige werkmap bestaat.
Items filteren uit een iterable
De ingebouwde functie any() kan ook worden gebruikt met een generator-expressie als argument en items uit een iterable filteren. In dit voorbeeld zoekt any() naar minstens één item in een lijst met woordenboeken die een persoon vertegenwoordigen wiens leeftijd lager is dan 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.
De generator-expressie levert True of False op, afhankelijk van de waarde die hoort bij de sleutel "age" van elk woordenboek. Een generator-expressie kan in any() worden gebruikt omdat deze iterable is.
Nog eens kijken naar luie evaluatie in Python's any()
Het vorige voorbeeld kan ook aantonen dat any() lui wordt geëvalueerd. Bekijk de volgende wijziging aan de lijst met woordenboeken:
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.
Het vierde woordenboek in records bevat geen item met de sleutel "age". Toch geeft de code geen fout wanneer geprobeerd wordt de waarde op te halen die bij "age" hoort voor dit item, omdat any() eerder in het proces al een truthy waarde vond. De functie kortsluit zodra hij de eerste truthy waarde tegenkomt.
De code werpt een KeyError als het woordenboek waarin de sleutel "age" ontbreekt, vóór items komt met een leeftijd onder de 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'
Dit voorbeeld is bedoeld om het kortsluitgedrag bij het gebruik van Python's any() te demonstreren. Er is een alternatief als de code geen excepties mag opwerpen voor items zonder een sleutel "age". De code kan de woordenboekmethode .get() met een standaardwaarde gebruiken in plaats van een woordenboekwaarde op te vragen met vierkante haken. De if-instructie kan worden vervangen door de volgende versie als het standaardgedrag is om aan te nemen dat items zonder leeftijd geen minderjarigen zijn:
if any(record.get("age", 18) < 18 for record in records):
# ...
Als de code moet aannemen dat elk item zonder leeftijd een minderjarige is, moet de standaardwaarde lager zijn dan 18.
Python: any() vs. all()
Python's any() heeft een bijbehorende functie, all(). Deze ingebouwde functie accepteert ook een iterable en retourneert True als alle items van de iterable truthy zijn.
Neem een voorbeeld van eerder in deze tutorial om gebruikersinvoer te valideren. Python's any() is handig als de toepassing minstens één geldige invoer vereist. all() kan echter worden gebruikt als alle gebruikersinvoer geldig moet zijn:
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
Als echter alle strings in de gebruikersinvoer niet leeg zijn, retourneert all() True:
user_inputs = ["5.99", "10.99", "19.99"]
# …
At least one valid input present
All inputs are valid
Net als any() wordt de ingebouwde all() lui geëvalueerd. De functie kortsluit zodra hij de eerste falsy waarde vindt.
Conclusie
Python's any() bepaalt of een van de items in een iterable truthy is. De functie retourneert True als minstens één item in de iterable True is of naar True evalueert wanneer het naar een Booleaan wordt gecast. Hoewel je dezelfde output met een lus kunt bereiken, biedt deze ingebouwde functie een beter leesbare en efficiëntere oplossing.
Ik studeerde natuurkunde en wiskunde op bachelorniveau aan de Universiteit van Malta. Daarna verhuisde ik naar Londen en behaalde ik mijn PhD in natuurkunde aan Imperial College. Ik werkte aan nieuwe optische technieken om het menselijk netvlies in beeld te brengen. Nu richt ik me op schrijven over Python, communiceren over Python en lesgeven in Python.
Onderwerpen

