Any & All

any() & all() sind durchaus praktisch.

Doch etwas sollte man beachten.

  • Um zu wissen ob eine oder alle Bedingungen wahr sind, werden alle evaluiert.
  • Das ist anders, als wenn man diese mit and & or verknüpft

Wir haben diese Funktionen:

def tt(msg):
    print('t', msg)
    return True

def ff(msg):
    print('f', msg)
    return False

Verknüpft man diese mit and so sieht man, dass die Kette wie erwartet am vorletzten Element abbricht:

>>> tt(1) and tt(2) and ff(3) and tt(4)
t 1
t 2
f 3
False

all() führt jedoch alle Funktionen in der Kette aus:

>>> all([tt(1), tt(2), ff(3), tt(4)])
t 1
t 2
f 3
t 4
False

Dreht man die Funktionen um, und nutzt das or, so wird wieder vorzeitig abbgebrochen:

>>> ff(1) or ff(2) or tt(3) or ff(4)
f 1
f 2
t 3
True

any() evaluiert aber wieder alle Elemente:

>>> any([ff(1), ff(2), tt(3), ff(4)])
f 1
f 2
t 3
f 4
True

Merke

Es ist nicht möglich Funktionen mit any() oder all() zu verketten, in der Hoffnung dass die gesamte Kette abbricht, wenn eine Funktionen fehlschlägt..

Die Begründung ist recht simpel: Beide Funktionen bekommen ein iterable (hier eine Liste) übergeben.

Um die Liste erst mal erstellen zu können, muss der Interpreter alle Elemente evaluieren. Dies sieht man so:

>>> [tt(1), ff(2)]
t 1
f 2
[True, False]

Man kann all() & any() dennoch dazu überreden vorzeitig abzubrechen, man muss aber ein bisschen improvisieren:

>>> all(f(n) for n, f in enumerate([tt, tt, ff, tt], start=1))
t 1
t 2
f 3
False