Jak działają Python anyi allfunkcje?
anyi allweź iterable i zwróć, Truejeśli są jakieś i wszystkie (odpowiednio) elementy 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
Jeśli iteracje są puste, anyzwraca Falsei allzwraca True.
>>> any([]), all([])
(False, True)
Demonstrowałem dzisiaj alli anydla uczniów w klasie. Byli w większości zdezorientowani co do wartości zwracanych dla pustych iteracji. Wyjaśnienie tego w ten sposób spowodowało włączenie wielu żarówek.
Skrótowe zachowanie
Oni, anyi allzarówno spojrzenie na chorobę, która pozwala im przestać oceny. Pierwsze przykłady, które podałem, wymagały od nich oceny wartości logicznej dla każdego elementu na całej liście.
(Zauważ, że literał listy sam w sobie nie jest leniwie oceniany - można to uzyskać za pomocą Iteratora - ale służy to wyłącznie celom ilustracyjnym).
Oto implementacja Pythona dla wszystkich:
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!
Oczywiście rzeczywiste implementacje są napisane w C i są znacznie wydajniejsze, ale możesz zastąpić powyższe i uzyskać te same wyniki dla kodu w tej (lub innej) odpowiedzi.
all
allsprawdza, czy elementy mają być False(aby mógł zwrócić False), a następnie zwraca, Truejeśli żaden z nich nie był 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
Sposób anydziałania polega na tym, że sprawdza, czy istnieją elementy True(aby mógł zwrócić True), then it returnsFalse if none of them wereTrue`.
>>> 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!
Myślę, że jeśli weźmiesz pod uwagę krótkie zachowanie, intuicyjnie zrozumiesz, jak one działają, bez konieczności odwoływania się do Tabeli Prawdy.
Dowody alli anyskróty:
Najpierw utwórz noisy_iterator:
def noisy_iterator(iterable):
for i in iterable:
print('yielding ' + repr(i))
yield i
a teraz przejdźmy głośno do list, korzystając z naszych przykładów:
>>> 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
Widzimy allzatrzymania na pierwszym fałszywym czeku logicznym.
I anyzatrzymuje się przy pierwszym teście logicznym True:
>>> 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
Źródło
Spójrzmy na źródło, aby potwierdzić powyższe.
Oto źródłoany :
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;
}
A oto źródłoall :
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;
}