Gegenteil einer beliebigen () Funktion

72

Mit der in Python integrierten Funktion any(iterable)können Sie schnell überprüfen, ob bool(element)es sich Trueum einen iterierbaren Typ handelt.

>>> l = [None, False, 0]
>>> any(l)
False
>>> l = [None, 1, 0]
>>> any(l)
True

Aber gibt es in Python eine elegante Art und Weise, die den gegenteiligen Effekt erzielen könnte any(iterable)? Wenn dies der Fall ist, bool(element) is Falsekehren Sie Truewie im folgenden Beispiel zurück:

>>> l = [True, False, True]
>>> any_false(l)
>>> True
Ekeyme Mo.
quelle
6
Ihre Frage wurde bereits von Jack Aidley richtig beantwortet. Vielleicht möchten Sie in en.wikipedia.org/wiki/De_Morgan's_laws nach der Theorie dahinter suchen .
VPfB
2
Die Antwort von JackAidley und Deceze kann je nach Problem hilfreich sein. Beachten Sie, dass "jedes Element ist falsch" nicht dasselbe ist wie "kein Element ist wahr" - sie haben unterschiedliche Antworten für das leere Array.
Kos
1
Beachten Sie, dass allRenditen Trueauf leere iterable “ - natürlich tut es . Hast du etwas anderes erwartet?
Bergi
1
@Bergi Nein, ich möchte nur einige Flash-Leute auf diese interessante Funktion aufmerksam machen. Stimmt etwas mit meinem Wort nicht?
Ekeyme Mo
@EkeymeMo: Keine Ahnung, klang wie eine Warnung, als wollte man etwas vermeiden. Oder vielleicht bin es nur ich.
Bergi

Antworten:

122

Es gibt auch die allFunktion, die das Gegenteil von dem tut, was Sie wollen. Sie gibt zurück, Trueob alle vorhanden sind Trueund Falseob welche vorhanden sind False. Deshalb können Sie einfach tun:

not all(l)
Jack Aidley
quelle
22
Nicht sicher, was OP will, wenn iterable leer ist, aber es ist erwähnenswert, allgibt True bei leer iterable zurück.
Lafexlos
1
@Lafexlos Guter Punkt, es lohnt sich immer, die Endpunkte zu berücksichtigen. Ich würde vermuten, dass Falsefür []die richtige Antwort ist; was dieser Code aber das OP geben müsste.
Jack Aidley
6
Denn all(...)Sie können jederzeit Truezur Argumentliste hinzufügen , ohne die Ausgabe zu ändern. Trueist ein "neutrales Element" (genau wie 0 für die Addition, 1 für die Multiplikation sind neutrale Elemente). Deshalb gibt es leere all()Retouren True. Für any()das neutrale Element ist False.
VPfB
1
@Fermiparadox: Wenn Sie einige schnelle Timings durchführen, ist dies viel schneller als anyerwartet, da alles integriert ist. Der Ansatz von Deceze ist jedoch allgemeiner anwendbar.
Jack Aidley
15
+1 Ein wenig Kenntnis der mathematischen Logik kann auf lange Sicht viel Zeit sparen: ∃x: ¬xentspricht ¬(∀x: x). Siehe hier
BlueRaja - Danny Pflughoeft
48

Schreiben Sie einen Generatorausdruck, der Ihren benutzerdefinierten Zustand testet. Sie sind nicht nur an den Standard- Wahrheitstest gebunden :

any(not i for i in l)
täuschen
quelle
2
Ja, vielleicht any(bool(i) == False for i in l)ist es besser. Recht? None == Falseist False, aber das will ich nicht. bool(None) == FalseistTrue
Ekeyme Mo
2
In diesem Fall not i for i in lwäre wahrscheinlich am besten.
Täuschung
4
@EkeymeMo Vermeiden Sie ==den Vergleich mit Booleschen Werten. Verwenden Sie einfach den bloßen Wert, z. if value: .... Wenn Sie jedoch unbedingt prüfen müssen, ob ein Objekt eher ein Boolescher als ein wahrheitsgemäßer Wert ist, verwenden Sie is. Andernfalls können Sie unerwartete Ergebnisse erzielen - z. 1 == Trueist wahr, aber 2 == Truefalsch.
Dünen
4
Dies ist deutlich langsamer alsnot all(l)
dawg
1
@Barmar allwird kurzschließen, sobald es trifft False; Ich gehe davon aus, dass der fest codierte C-Stil, nach dem Falsenot i
gesucht
16

Nun, die Implementierung von anyist gleichbedeutend mit:

def any(iterable):
    for element in iterable:
        if element:
            return True
    return False

Schalten Sie einfach die Bedingung von if elementauf if not element:

def reverse_any(iterable):
    for element in iterable:
        if not element:
            return True
    return False

Ja, dies nutzt natürlich nicht die Geschwindigkeit der integrierten Funktionen anyoder allwie die anderen Antworten, aber es ist eine gut lesbare Alternative.

Dimitris Fasarakis Hilliard
quelle
5
@ JackAidley Natürlich ist es so , ich habe nie etwas anderes behauptet. Ich habe gerade eine Alternative hinzugefügt. Denken Sie daran, anyund allsind im Allgemeinen mystifizieren , um neue Benutzer an ihrer rauen Implementierung sucht im Allgemeinen hilft.
Dimitris Fasarakis Hilliard
9

Du kannst tun:

>>> l = [True, False, True]
>>> False in map(bool, l)
True

Denken Sie daran, dass mapin Python 3 ein Generator ist. Für Python 2 möchten Sie wahrscheinlich verwendenimap


Mea Culpa: Nach dem Timing ist die von mir angebotene Methode zweifellos die langsamste

Das schnellste ist not all(l)oder not next(filterfalse(bool, it), True)was nur eine alberne itertools Variante ist. Verwenden Sie die Jack Aidleys- Lösung .

Timing-Code:

from itertools import filterfalse

def af1(it):
    return not all(it)

def af2(it):
    return any(not i for i in it)   

def af3(iterable):
    for element in iterable:
        if not element:
            return True
    return False    

def af4(it):
    return False in map(bool, it)   

def af5(it):
    return not next(filterfalse(bool, it), True)    

if __name__=='__main__':
    import timeit   
    for i, l in enumerate([[True]*1000+[False]+[True]*999, # False in the middle
                           [False]*2000, # all False
                            [True]*2000], # all True
                            start=1): 
        print("case:", i)
        for f in (af1, af2, af3, af4, af5):
            print("   ",f.__name__, timeit.timeit("f(l)", setup="from __main__ import f, l", number=100000), f(l) )

Ergebnisse:

case: 1
    af1 0.45357259700540453 True
    af2 4.538436588976765 True
    af3 1.2491040650056675 True
    af4 8.935278153978288 True
    af5 0.4685744970047381 True
case: 2
    af1 0.016299808979965746 True
    af2 0.04787631600629538 True
    af3 0.015038023004308343 True
    af4 0.03326922300038859 True
    af5 0.029870904982089996 True
case: 3
    af1 0.8545824179891497 False
    af2 8.786235476000002 False
    af3 2.448748088994762 False
    af4 17.90895140200155 False
    af5 0.9152941330103204 False
dawg
quelle