Kurs
Eine häufige Aufgabe in Python-Programmen ist zu prüfen, ob mindestens ein Element einer Datenstruktur True ist.
Zwar lässt sich eine Schleife schreiben, die über ein Iterable iteriert und jedes Element auf True oder False prüft, doch Pythons Funktion any() ist dafür effizienter und "pythonic".
Dieses Tutorial stellt Pythons eingebaute Funktion any() vor und zeigt mehrere Beispiele und Anwendungsfälle.
KI-Upskilling für Einsteiger
Was macht Pythons any()-Funktion?
Pythons any() gehört zu den eingebauten Funktionen. Sie akzeptiert ein Iterable wie eine Liste oder ein Tupel und gibt True zurück, wenn mindestens ein Wert im Iterable truthy ist. Ein truthy Wert wird als True ausgewertet, wenn er mit bool() in einen Boolean umgewandelt wird. Sind alle Werte im Iterable falsy, liefert any() False:
print(any([True, False, False, True]))
print(any([False, False, False, False]))
print(any([0, 0, 5, 0]))
True
False
True
Das Iterable kann Boolean-Werte oder andere Objekte enthalten, da alle Objekte in einem booleschen Kontext als True oder False ausgewertet werden. Im dritten Beispiel enthält die Liste vier Ganzzahlen. Die Ganzzahl 0 ist falsy, alle von Null verschiedenen Zahlen sind truthy. Um den Unterschied zwischen truthy und falsy besser zu verstehen, lies diesen Blog über logische Operatoren in Python.
Ist das Iterable leer, gibt any() False zurück, da es in einem leeren Iterable keine truthy Werte gibt:
print(any([]))
False
Im nächsten Abschnitt schauen wir uns genauer an, wie any() funktioniert.
Wie funktioniert any()?
Die eingebaute Funktion any() akzeptiert jedes Iterable als Argument. Ein Iterable ist jede Datenstruktur, über die Python iterieren kann.
Betrachte folgendes Tupel:
an_iterable = ("", 0.0, "DataCamp", False, [])
Das Tupel enthält mehrere Objekte mit unterschiedlichen Typen. Einige davon sind falsy:
- Der leere String
"" - Die Gleitkommazahl
0.0 - Der Boolean
False - Die leere Liste
[]
Diese Objekte sind falsy, weil sie bei Übergabe an bool() als False ausgewertet werden.
Der nicht leere String "DataCamp" ist truthy.
Eine einfache Möglichkeit zu prüfen, ob mindestens ein Element truthy ist, ist eine for-Schleife:
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
Das ist jedoch ineffizient, denn die Funktion muss nur feststellen, ob es mindestens einen truthy Wert gibt. Sobald ein truthy Wert gefunden ist, muss der Rest des Iterables nicht weiter geprüft werden. Die Funktion kann so geändert werden, dass sie beim ersten truthy Wert sofort zurückkehrt:
def check_if_contains_truthy(data):
for item in data:
if item:
return True
return False
print(check_if_contains_truthy(an_iterable))
True
Ein return beendet die Ausführung der Funktion. Findet die Funktion also den ersten truthy Wert, gibt sie True zurück und iteriert nicht weiter. False wird nur zurückgegeben, wenn die for-Schleife alle Elemente durchläuft und keines truthy ist.
Die eingebaute Funktion any() folgt demselben Muster und bricht beim ersten truthy Wert ab (Short-Circuiting). Diese Lazy-Evaluation verhindert unnötige Operationen und verbessert die Performance. Pythons any() ist damit eine effizientere Version der obigen Funktion. Das zeigt auch timeit() aus dem Modul timeit, das die Ausführungszeit eines Statements misst:
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
Das erste Argument von timeit() ist ein String mit dem auszuführenden Statement. Das zweite Argument legt fest, wie oft es ausgeführt wird. Hier werden beide Statements 10.000.000-mal ausgeführt, um aussagekräftige Zeiten zu erhalten. Das letzte Argument übergibt die globalen Variablen an timeit().
Pythons any() ist schneller als check_if_contains_truthy(). Um festzustellen, ob ein Iterable mindestens einen truthy Wert enthält, ist any() die pythonischere und effizientere Wahl gegenüber einer for-Schleife.
Anwendungsfälle für any()
Schauen wir uns ein paar Anwendungsfälle für Pythons any() an.
Prüfen, ob mindestens eine Nutzereingabe gültig ist
Angenommen, mehrere Nutzereingaben wurden in einer Liste oder einem Tupel gesammelt. Ein Programm muss vielleicht prüfen, ob mindestens eine Eingabe gültig ist, zum Beispiel ein nicht leerer String:
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
Da einer der Strings nicht leer ist, liefert any() True, und der Code im if-Zweig wird ausgeführt.
Prüfen, ob mindestens eine Datei existiert
Mit any() lässt sich prüfen, ob mindestens eine Datei aus einer Liste von Dateinamen in einem Verzeichnis existiert:
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
Der Code ermittelt das aktuelle Arbeitsverzeichnis über das Modul pathlib und Path.cwd(). Er legt eine Datei test_file.txt im Arbeitsverzeichnis an, damit sich das Beispiel leicht testen lässt. Mit Pythons any() wird geprüft, ob mindestens einer der Dateinamen im aktuellen Arbeitsverzeichnis existiert.
Elemente aus einem Iterable filtern
Die eingebaute Funktion any() kann auch mit einem Generatorausdruck als Argument genutzt werden und Elemente aus einem Iterable herausfiltern. In diesem Beispiel sucht any() nach mindestens einem Eintrag in einer Liste von Dictionaries, der eine Person mit einem Alter unter 18 repräsentiert:
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.
Der Generatorausdruck liefert je nach Wert zum Schlüssel "age" jedes Dictionaries True oder False. Ein Generatorausdruck kann in any() verwendet werden, da er iterierbar ist.
Noch einmal: Lazy-Evaluation in Pythons any()
Das vorige Beispiel zeigt auch, dass any() lazy ausgewertet wird. Betrachte diese Anpassung der Dictionary-Liste:
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.
Das vierte Dictionary in records enthält keinen Eintrag mit dem Schlüssel "age". Trotzdem wirft der Code beim Zugriff auf "age" für dieses Element keinen Fehler, da any() zuvor bereits einen truthy Wert gefunden hat. Die Funktion bricht beim ersten truthy Wert ab.
Der Code löst einen KeyError aus, wenn das Dictionary ohne Schlüssel "age" vor allen Einträgen mit einem Alter unter 18 steht:
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'
Dieses Beispiel soll das Short-Circuiting-Verhalten von any() verdeutlichen. Es gibt eine Alternative, wenn für Einträge ohne Schlüssel "age" keine Ausnahme ausgelöst werden soll: Statt mit eckigen Klammern auf einen Dictionary-Wert zuzugreifen, kann die Dictionary-Methode .get() mit einem Standardwert verwendet werden. Der if-Ausdruck kann so ersetzt werden, wenn standardmäßig davon ausgegangen werden soll, dass Einträge ohne Alter keine Minderjährigen sind:
if any(record.get("age", 18) < 18 for record in records):
# ...
Soll der Code annehmen, dass jeder Eintrag ohne Alter minderjährig ist, muss der Standardwert kleiner als 18 sein.
Python: any() vs. all()
Zu any() gehört die Schwesterfunktion all(). Diese eingebaute Funktion akzeptiert ebenfalls ein Iterable und gibt True zurück, wenn alle Elemente des Iterables truthy sind.
Betrachte ein früheres Beispiel zur Validierung von Eingaben. any() ist hilfreich, wenn die Anwendung mindestens eine gültige Eingabe erfordert. Sollen jedoch alle Eingaben gültig sein, kommt all() ins Spiel:
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
Sind hingegen alle Strings in den Nutzereingaben nicht leer, gibt all() True zurück:
user_inputs = ["5.99", "10.99", "19.99"]
# …
At least one valid input present
All inputs are valid
Ähnlich wie any() wird auch all() lazy ausgewertet. Die Funktion bricht beim ersten falsy Wert ab.
Fazit
Pythons any() prüft, ob eines der Elemente in einem Iterable truthy ist. Die Funktion gibt True zurück, wenn mindestens ein Element True ist oder in einem booleschen Kontext zu True wird. Auch wenn man dasselbe Ergebnis mit einer Schleife erreichen kann, bietet diese eingebaute Funktion eine lesbarere und effizientere Lösung.
Verdiene eine Top-KI-Zertifizierung
Ich habe Physik und Mathematik auf UG-Ebene an der Universität Malta studiert. Dann zog ich nach London und machte meinen Doktor in Physik am Imperial College. Ich habe an neuartigen optischen Techniken zur Abbildung der menschlichen Netzhaut gearbeitet. Jetzt konzentriere ich mich darauf, über Python zu schreiben, über Python zu kommunizieren und Python zu unterrichten.
