Wie funktionieren alle Funktionen von Python?

225

Ich versuche zu verstehen, wie die any()und die in all()Python integrierten Funktionen funktionieren.

Ich versuche, die Tupel so zu vergleichen, dass sie zurückgegeben werden, wenn sich ein Wert unterscheidet, Trueund wenn sie alle gleich sind, wird er zurückgegeben False. Wie arbeiten sie in diesem Fall, um [Falsch, Falsch, Falsch] zurückzugeben?

dist ein defaultdict(list).

print d['Drd2']
# [[1, 5, 0], [1, 6, 0]]
print list(zip(*d['Drd2']))
# [(1, 1), (5, 6), (0, 0)]
print [any(x) and not all(x) for x in zip(*d['Drd2'])]
# [False, False, False]

Meines Wissens sollte dies ausgegeben werden

# [False, True, False]

da (1,1) gleich sind, sind (5,6) unterschiedlich und (0,0) gleich.

Warum wird für alle Tupel False ausgewertet?

O.rka
quelle
4
any (iterable): Gibt bei der ersten Begegnung mit dem Truthy-Objekt true zurück. Andernfalls wird false zurückgegeben. all (iterable): Gibt Flase bei der ersten Begegnung mit einem falschen Objekt zurück, andernfalls wird true zurückgegeben.
shadow0359

Antworten:

375

Sie können sich grob anyund allals eine Reihe von logischen orbzw. andOperatoren vorstellen.

irgendein

anywird zurückkehren, Truewenn mindestens eines der Elemente Wahrheit ist. Lesen Sie mehr über das Testen von Wahrheitswerten.

alles

allwird Truenur zurückkehren, wenn alle Elemente wahr sind.

Wahrheitstabelle

+-----------------------------------------+---------+---------+
|                                         |   any   |   all   |
+-----------------------------------------+---------+---------+
| All Truthy values                       |  True   |  True   |
+-----------------------------------------+---------+---------+
| All Falsy values                        |  False  |  False  |
+-----------------------------------------+---------+---------+
| One Truthy value (all others are Falsy) |  True   |  False  |
+-----------------------------------------+---------+---------+
| One Falsy value (all others are Truthy) |  True   |  False  |
+-----------------------------------------+---------+---------+
| Empty Iterable                          |  False  |  True   |
+-----------------------------------------+---------+---------+

Anmerkung 1: Der leere iterierbare Fall wird in der offiziellen Dokumentation wie folgt erläutert

any

Rückgabe, Truewenn ein Element der Iterable wahr ist. Wenn die Iterable leer ist, kehren Sie zurückFalse

Da keines der Elemente wahr ist, wird Falsein diesem Fall zurückgegeben.

all

Rückgabe, Truewenn alle Elemente der Iterable wahr sind ( oder wenn die Iterable leer ist ).

Da keines der Elemente falsch ist, wird Truein diesem Fall zurückgegeben.


Anmerkung 2:

Eine weitere wichtige Sache wissen anyund allist, wird es Kurzschluss , die Ausführung, sobald sie wissen , das Ergebnis. Der Vorteil ist, dass nicht die gesamte Iterierbarkeit verbraucht werden muss. Beispielsweise,

>>> multiples_of_6 = (not (i % 6) for i in range(1, 10))
>>> any(multiples_of_6)
True
>>> list(multiples_of_6)
[False, False, False]

Hier (not (i % 6) for i in range(1, 10))ist ein Generatorausdruck, der zurückgibt, Truewenn die aktuelle Zahl innerhalb von 1 und 9 ein Vielfaches von 6 ist. anyIteriert das multiples_of_6und wenn es sich trifft 6, findet es einen Wahrheitswert, so dass es sofort zurückkehrt Trueund der Rest von multiples_of_6nicht iteriert wird. Das ist , was wir sehen , wenn wir drucken list(multiples_of_6), das Ergebnis 7, 8und 9.

Diese hervorragende Sache wird in dieser Antwort sehr geschickt verwendet .


Mit diesem Grundverständnis tun Sie dies, wenn wir uns Ihren Code ansehen

any(x) and not all(x)

was sicherstellt, dass zumindest einer der Werte die Wahrheit ist, aber nicht alle. Deshalb kehrt es zurück [False, False, False]. Wenn Sie wirklich überprüfen möchten, ob beide Zahlen nicht gleich sind,

print [x[0] != x[1] for x in zip(*d['Drd2'])]
thefourtheye
quelle
@anyone: Was tun wir, wenn ich alle außer dem Fall verwenden muss, in dem True für eine leere Liste zurückgegeben wird? Ich verstehe die Logik hinter True nicht, wenn die Liste leer ist ... was bedeutet, dass alle ([]) == True
JavaSa
1
@JavaSa Sie können explizit überprüfen, ob die Liste leer ist. Ich glaube so etwas bool(data) and all(...)sollte funktionieren.
thefourtheye
43

Wie funktionieren Pythons anyund allFunktionen?

anyund allnehmen Sie iterables und geben Sie zurück, Truewenn alle Elemente vorhanden sind True.

>>> any([0, 0.0, False, (), '0']), all([1, 0.0001, True, (False,)])
(True, True)            #   ^^^-- truthy non-empty string
>>> any([0, 0.0, False, (), '']), all([1, 0.0001, True, (False,), {}])
(False, False)                                                #   ^^-- falsey

Wenn die Iterables leer sind, anykehrt Falseund allkehrt True.

>>> any([]), all([])
(False, True)

Ich habe heute demonstriert allund anyfür Schüler im Unterricht. Sie waren größtenteils verwirrt über die Rückgabewerte für leere Iterables. Wenn man es so erklärt, schalten sich viele Glühbirnen ein.

Verknüpfungsverhalten

Sie, anyund allbeide suchen nach einer Bedingung , dass sie zu stoppen Auswertung ermöglicht. Bei den ersten Beispielen mussten sie den Booleschen Wert für jedes Element in der gesamten Liste auswerten.

(Beachten Sie, dass das Listenliteral selbst nicht träge ausgewertet wird - dies könnte mit einem Iterator erreicht werden -, dies dient jedoch nur zur Veranschaulichung.)

Hier ist eine Python-Implementierung von allem:

def any(iterable):
    for i in iterable:
        if i:
            return True
    return False # for an empty iterable, any returns False!

def all(iterable):
    for i in iterable:
        if not i:
            return False
    return True  # for an empty iterable, all returns True!

Natürlich sind die realen Implementierungen in C geschrieben und viel leistungsfähiger, aber Sie können die oben genannten ersetzen und die gleichen Ergebnisse für den Code in dieser (oder einer anderen) Antwort erhalten.

all

allprüft , ob Elemente vorhanden sind False(damit sie zurückkehren können False), und gibt sie zurück, Truewenn keines von ihnen vorhanden ist False.

>>> all([1, 2, 3, 4])                 # has to test to the end!
True
>>> all([0, 1, 2, 3, 4])              # 0 is False in a boolean context!
False  # ^--stops here!
>>> all([])
True   # gets to end, so True!

any

Die Funktionsweise anybesteht darin, dass nach Elementen gesucht wird True(damit True), then it returnsFalse if none of them wereTrue zurückgegeben werden kann`.

>>> any([0, 0.0, '', (), [], {}])     # has to test to the end!
False
>>> any([1, 0, 0.0, '', (), [], {}])  # 1 is True in a boolean context!
True   # ^--stops here!
>>> any([])
False   # gets to end, so False!

Ich denke, wenn Sie das Abkürzungsverhalten berücksichtigen, werden Sie intuitiv verstehen, wie sie funktionieren, ohne auf eine Wahrheitstabelle verweisen zu müssen.

Nachweis allund anyAbkürzung:

Erstellen Sie zunächst einen noisy_iterator:

def noisy_iterator(iterable):
    for i in iterable:
        print('yielding ' + repr(i))
        yield i

Lassen Sie uns nun anhand unserer Beispiele die Listen geräuschvoll durchlaufen:

>>> all(noisy_iterator([1, 2, 3, 4]))
yielding 1
yielding 2
yielding 3
yielding 4
True
>>> all(noisy_iterator([0, 1, 2, 3, 4]))
yielding 0
False

Wir können allStopps beim ersten False Boolean Check sehen.

Und anystoppt beim ersten True Boolean Check:

>>> any(noisy_iterator([0, 0.0, '', (), [], {}]))
yielding 0
yielding 0.0
yielding ''
yielding ()
yielding []
yielding {}
False
>>> any(noisy_iterator([1, 0, 0.0, '', (), [], {}]))
yielding 1
True

Die Quelle

Schauen wir uns die Quelle an, um das oben Gesagte zu bestätigen.

Hier ist die Quelle fürany :

static PyObject *
builtin_any(PyObject *module, PyObject *iterable)
{
    PyObject *it, *item;
    PyObject *(*iternext)(PyObject *);
    int cmp;

    it = PyObject_GetIter(iterable);
    if (it == NULL)
        return NULL;
    iternext = *Py_TYPE(it)->tp_iternext;

    for (;;) {
        item = iternext(it);
        if (item == NULL)
            break;
        cmp = PyObject_IsTrue(item);
        Py_DECREF(item);
        if (cmp < 0) {
            Py_DECREF(it);
            return NULL;
        }
        if (cmp > 0) {
            Py_DECREF(it);
            Py_RETURN_TRUE;
        }
    }
    Py_DECREF(it);
    if (PyErr_Occurred()) {
        if (PyErr_ExceptionMatches(PyExc_StopIteration))
            PyErr_Clear();
        else
            return NULL;
    }
    Py_RETURN_FALSE;
}

Und hier ist die Quelle fürall :

static PyObject *
builtin_all(PyObject *module, PyObject *iterable)
{
    PyObject *it, *item;
    PyObject *(*iternext)(PyObject *);
    int cmp;

    it = PyObject_GetIter(iterable);
    if (it == NULL)
        return NULL;
    iternext = *Py_TYPE(it)->tp_iternext;

    for (;;) {
        item = iternext(it);
        if (item == NULL)
            break;
        cmp = PyObject_IsTrue(item);
        Py_DECREF(item);
        if (cmp < 0) {
            Py_DECREF(it);
            return NULL;
        }
        if (cmp == 0) {
            Py_DECREF(it);
            Py_RETURN_FALSE;
        }
    }
    Py_DECREF(it);
    if (PyErr_Occurred()) {
        if (PyErr_ExceptionMatches(PyExc_StopIteration))
            PyErr_Clear();
        else
            return NULL;
    }
    Py_RETURN_TRUE;
}
Aaron Hall
quelle
1
Hinweis: Dies steht im Einklang mit mathematischen Prädikaten: "für alle" und "es existiert". Die Verwirrung kann sein, dass "FOR ALL" und "FOR ANY" Synonyme in anderen Kontexten sind ... en.wikipedia.org/wiki/List_of_logic_symbols
mcoolive
1
@ thanos.a es ist in Python/bltinmodule.c- ich habe es oben hinzugefügt.
Aaron Hall
14

Ich weiß, dass dies alt ist, aber ich dachte, es könnte hilfreich sein, zu zeigen, wie diese Funktionen im Code aussehen. Dies zeigt wirklich die Logik, besser als Text oder eine Tabelle IMO. In Wirklichkeit sind sie eher in C als in reinem Python implementiert, aber diese sind äquivalent.

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

def all(iterable):
    for item in iterable:
        if not item:
            return False
    return True

Insbesondere können Sie sehen, dass das Ergebnis für leere Iterables nur das natürliche Ergebnis ist, kein Sonderfall. Sie können auch das Kurzschlussverhalten sehen; Es wäre tatsächlich mehr Arbeit , wenn es keinen Kurzschluss gäbe .

Als Guido van Rossum (der Schöpfer von Python) das erste Hinzufügen von any()und vorschlugall() , erklärte er sie, indem er genau die obigen Codeausschnitte veröffentlichte.

Arthur Tacca
quelle
10

Der fragliche Code, nach dem Sie fragen, stammt aus meiner hier gegebenen Antwort . Es sollte das Problem des Vergleichs mehrerer Bit-Arrays lösen, dh Sammlungen von 1und 0.

anyund allsind nützlich, wenn Sie sich auf die "Wahrhaftigkeit" von Werten verlassen können - dh auf ihren Wert in einem booleschen Kontext. 1 ist Trueund 0 ist False, eine Annehmlichkeit, die diese Antwort nutzte. 5 ist zufällig auch so True, wenn Sie das in Ihre möglichen Eingaben mischen ... na ja. Funktioniert nicht

Sie könnten stattdessen so etwas tun:

[len(set(x)) > 1 for x in zip(*d['Drd2'])]

Es fehlt die Ästhetik der vorherigen Antwort ( das Aussehen hat mir sehr gut gefallen any(x) and not all(x)), aber es erledigt den Job.

Roippi
quelle
Colberts Einfluss erreicht CS / CE: en.wikipedia.org/wiki/Truthiness ? Sprechen wir über Fuzzy-Logik? : D
Geof Sawaya
Da das OP gefragt hat, Truewann die Werte unterschiedlich sind, sollte die Länge des Satzes 2 sein, nicht 1.
Wombatonfire
@wombatonfire haha ​​guter Fang. Ich habe meine 7-jährige Antwort angepasst :)
Roippi
Gute Antworten altern nicht :) Netter Ansatz mit einem Set.
Wombatonfire
7
>>> any([False, False, False])
False
>>> any([False, True, False])
True
>>> all([False, True, True])
False
>>> all([True, True, True])
True
Job in
quelle
4
s = "eFdss"
s = list(s)
all(i.islower() for i in s )   # FALSE
any(i.islower() for i in s )   # TRUE
David Gladson
quelle
1

Das Konzept ist einfach:

M =[(1, 1), (5, 6), (0, 0)]

1) print([any(x) for x in M])
[True, True, False] #only the last tuple does not have any true element

2) print([all(x) for x in M])
[True, True, False] #all elements of the last tuple are not true

3) print([not all(x) for x in M])
[False, False, True] #NOT operator applied to 2)

4) print([any(x)  and not all(x) for x in M])
[False, False, False] #AND operator applied to 1) and 3)
# if we had M =[(1, 1), (5, 6), (1, 0)], we could get [False, False, True]  in 4)
# because the last tuple satisfies both conditions: any of its elements is TRUE 
#and not all elements are TRUE 
DK250
quelle
0
list = [1,1,1,0]
print(any(list)) # will return True because there is  1 or True exists
print(all(list)) # will return False because there is a 0 or False exists
return all(a % i for i in range(3, int(a ** 0.5) + 1)) # when number is divisible it will return False else return True but the whole statement is False .
Ajmal Aamir
quelle