Come funzionano Python anye le allfunzioni?
anye allprende iterables e restituisce Truese tutti gli elementi (rispettivamente) sono 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
Se gli iterabili sono vuoti, anyrestituisce Falsee allrestituisce True.
>>> any([]), all([])
(False, True)
Stavo dimostrando alle anyper gli studenti in classe oggi. Erano per lo più confusi riguardo ai valori di ritorno per iterabili vuoti. Spiegarlo in questo modo ha causato l'accensione di molte lampadine.
Comportamento di scelta rapida
Essi, anye all, sia sguardo per una condizione che permette loro di smettere di valutazione. I primi esempi che ho fornito hanno richiesto loro di valutare il valore booleano per ciascun elemento dell'intero elenco.
(Nota che l'elenco letterale non è esso stesso valutato pigramente - potresti ottenerlo con un Iteratore - ma questo è solo a scopo illustrativo.)
Ecco un'implementazione Python di tutti e tutti:
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!
Ovviamente, le implementazioni reali sono scritte in C e sono molto più performanti, ma è possibile sostituire quanto sopra e ottenere gli stessi risultati per il codice in questa (o in qualsiasi altra) risposta.
all
allverifica la presenza di elementi False(in modo che possano essere restituiti False), quindi restituisce Truese nessuno di essi lo fosse 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
Il modo in cui anyfunziona è che controlla la presenza di elementi True(in modo che possa restituire 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!
Penso che se tieni presente il comportamento abbreviato, capirai intuitivamente come funzionano senza dover fare riferimento a una tabella di verità.
Prova alle anyscorciatoia:
Innanzitutto, crea un noisy_iterator:
def noisy_iterator(iterable):
for i in iterable:
print('yielding ' + repr(i))
yield i
e ora ripetiamo rumorosamente gli elenchi, usando i nostri esempi:
>>> 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
Possiamo vedere le allfermate sul primo controllo booleano Falso.
E si anyferma al primo vero controllo booleano:
>>> 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
La fonte
Diamo un'occhiata alla fonte per confermare quanto sopra.
Ecco la fonte perany :
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;
}
Ed ecco la fonte perall :
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;
}