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;
}