Como funcionam as funções anye o Python all?
anye allpegue iterables e retorne Truese houver algum ou todos (respectivamente) dos elementos 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 os iterables estiverem vazios, anyretornará Falsee allretornará True.
>>> any([]), all([])
(False, True)
Eu estava demonstrando alle anypara os alunos nas aulas hoje. Eles estavam principalmente confusos sobre os valores de retorno para iterables vazios. Explicá-lo dessa maneira fez com que muitas lâmpadas acendessem.
Comportamento de atalho
Eles, anye all, tanto olhar para uma condição que lhes permite parar de avaliar. Os primeiros exemplos que eu dei exigiram que eles avaliassem o booleano de cada elemento da lista inteira.
(Observe que o literal da lista não é avaliado preguiçosamente - você pode obtê-lo com um iterador - mas isso é apenas para fins ilustrativos.)
Aqui está uma implementação Python de todo e qualquer:
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!
Obviamente, as implementações reais são escritas em C e têm muito mais desempenho, mas você pode substituir as opções acima e obter os mesmos resultados para o código nesta (ou em qualquer outra) resposta.
all
allverifica a existência de elementos False(para que ele possa retornar False) e, em seguida, retorna Truese nenhum deles foi 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
A maneira como anyfunciona é que ele verifica se há elementos True(para que possa retornar True), then it returnsFalseif none of them were True`.
>>> 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 que, se você se lembrar do comportamento de atalho, entenderá intuitivamente como eles funcionam sem precisar fazer referência a uma Tabela da Verdade.
Evidência de all e anyatalho:
Primeiro, crie um noisy_iterator:
def noisy_iterator(iterable):
for i in iterable:
print('yielding ' + repr(i))
yield i
e agora vamos iterar ruidosamente nas listas, usando nossos exemplos:
>>> 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
Nós podemos ver all paradas na primeira verificação booleana falsa.
E anypara na primeira verificação booleana 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
A fonte
Vamos olhar a fonte para confirmar o acima.
Aqui está a fonte paraany :
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;
}
E aqui está a fonte paraall :
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;
}