¿Cómo funcionan todas y cada una de las funciones de Python?

225

Estoy tratando de entender cómo funcionan las funciones integradas any()y all()Python.

Estoy tratando de comparar las tuplas para que si algún valor es diferente, volverá Truey si son todos iguales, volverá False. ¿Cómo están trabajando en este caso para devolver [False, False, False]?

des un 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]

Que yo sepa, esto debería dar salida

# [False, True, False]

ya que (1,1) son iguales, (5,6) son diferentes y (0,0) son iguales.

¿Por qué está evaluando a Falso para todas las tuplas?

O.rka
fuente
44
any (iterable): devuelve verdadero en el primer encuentro del objeto Truthy; de lo contrario, devuelve falso. all (iterable): devuelve flase en el primer encuentro del objeto falso, de lo contrario devuelve true.
shadow0359

Respuestas:

375

Puede pensar aproximadamente anyy allcomo una serie de lógicos ory andoperadores, respectivamente.

alguna

anyregresará Truecuando al menos uno de los elementos sea ​​Verdad. Lea sobre la prueba del valor de la verdad.

todas

allTruesolo volverá cuando todos los elementos sean Verdad.

Mesa de la verdad

+-----------------------------------------+---------+---------+
|                                         |   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   |
+-----------------------------------------+---------+---------+

Nota 1: El caso iterable vacío se explica en la documentación oficial, como esta

any

Devuelve Truesi algún elemento del iterable es verdadero. Si el iterable está vacío, regreseFalse

Como ninguno de los elementos es verdadero, vuelve Falseen este caso.

all

Devuelve Truesi todos los elementos del iterable son verdaderos ( o si el iterable está vacío ).

Como ninguno de los elementos es falso, vuelve Trueen este caso.


Nota 2:

Otra cosa importante que debe saber anyy alles que cortocircuitará la ejecución en el momento en que sepan el resultado. La ventaja es que no es necesario consumir todo el iterable. Por ejemplo,

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

Aquí, (not (i % 6) for i in range(1, 10))hay una expresión generadora que regresa Truesi el número actual dentro de 1 y 9 es un múltiplo de 6. anyitera multiples_of_6y cuando se encuentra 6, encuentra un valor de Verdad, por lo que regresa de inmediato Truey el resto multiples_of_6no se repite. Eso es lo que vemos cuando imprimimos list(multiples_of_6), el resultado de7 , 8y 9.

Esta excelente cosa se usa muy inteligentemente en esta respuesta .


Con esta comprensión básica, si miramos su código, usted lo hace

any(x) and not all(x)

lo que garantiza que, al menos, uno de los valores sea Verdad, pero no todos. Por eso está volviendo [False, False, False]. Si realmente quisiera verificar si ambos números no son iguales,

print [x[0] != x[1] for x in zip(*d['Drd2'])]
thefourtheye
fuente
@ cualquiera: si necesito usar todo menos el caso en el que devuelve Verdadero para lista vacía no es aceptable, ¿qué hacemos? No entiendo la lógica detrás de dar True si la lista está vacía ... lo que significa todo ([]) == True
JavaSa
1
@JavaSa Puede verificar explícitamente si la lista está vacía. Creo que algo así bool(data) and all(...)debería funcionar.
thefourtheye
43

¿Cómo funcionan las funciones anyy de Python all?

anyy alltomar iterables y devolver Truesi alguno y todos (respectivamente) de los elementos son 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

Si los iterables están vacíos, anydevuelve Falsey alldevuelve True.

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

Me estaba manifestando ally anypara estudiantes en clase hoy. En su mayoría estaban confundidos acerca de los valores de retorno para iterables vacíos. Explicarlo de esta manera provocó que se encendieran muchas bombillas.

Comportamiento de atajos

Ellos anyy allambos buscan una condición que les permita dejar de evaluar. Los primeros ejemplos que les di requieren que evalúen el valor booleano para cada elemento en toda la lista.

(Tenga en cuenta que la lista literal no se evalúa perezosamente en sí misma ; podría obtener eso con un iterador , pero esto es solo para fines ilustrativos).

Aquí hay una implementación de Python de todos y cada uno:

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!

Por supuesto, las implementaciones reales están escritas en C y son mucho más eficaces, pero puede sustituir lo anterior y obtener los mismos resultados para el código en esta (o en cualquier otra) respuesta.

all

allcomprueba si hay elementos False(para que pueda regresar False), luego regresa Truesi ninguno de ellos lo fue 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

La forma en que anyfunciona es que comprueba si hay elementos True(para que pueda devolver 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!

Creo que si tiene en cuenta el comportamiento abreviado, comprenderá intuitivamente cómo funcionan sin tener que hacer referencia a una Tabla de Verdad.

Evidencia de allyany atajo:

Primero, crea un noisy_iterator:

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

y ahora solo recorramos las listas ruidosamente, usando nuestros ejemplos:

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

Podemos ver allparadas en el primer cheque falso booleano.

Y se anydetiene en la primera verificación booleana verdadera:

>>> 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 fuente

Miremos la fuente para confirmar lo anterior.

Aquí está la fuente deany :

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

Y aquí está la fuente deall :

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
fuente
1
Nota: esto es consistente con los predicados matemáticos: "para todos" y "existe". La confusión puede ser que "PARA TODOS" y "PARA CUALQUIERA" son sinónimos en otros contextos ... en.wikipedia.org/wiki/List_of_logic_symbols
mcoolive
1
@ thanos.a está en Python/bltinmodule.c- Lo agregué a lo anterior.
Aaron Hall
14

Sé que esto es antiguo, pero pensé que podría ser útil mostrar cómo se ven estas funciones en el código. Esto realmente ilustra la lógica, mejor que el texto o una tabla IMO. En realidad, se implementan en C en lugar de Python puro, pero son equivalentes.

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

En particular, puede ver que el resultado para iterables vacíos es solo el resultado natural, no un caso especial. También puede ver el comportamiento de cortocircuito; en realidad sería más trabajo para que no haya cortocircuito.

Cuando Guido van Rossum (el creador de Python) propuso por primera vez agregar any()yall() , los explicó simplemente publicando exactamente los fragmentos de código anteriores.

Arthur Tacca
fuente
10

El código en cuestión sobre el que está preguntando proviene de mi respuesta dada aquí . Estaba destinado a resolver el problema de comparar múltiples matrices de bits, es decir, colecciones de 1y 0.

anyy allson útiles cuando puede confiar en la "veracidad" de los valores, es decir, su valor en un contexto booleano. 1 es Truey 0 es False, una conveniencia que esa respuesta aprovechó. 5 también lo es True, así que cuando mezclas eso en tus posibles entradas ... bueno. No funciona

En su lugar, podría hacer algo como esto:

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

Carece de la estética de la respuesta anterior ( realmente me gustó la apariencia de any(x) and not all(x)), pero hace el trabajo.

roippi
fuente
La influencia de Colbert está llegando a CS / CE: en.wikipedia.org/wiki/Truthiness ? ¿Estamos hablando de lógica difusa? : D
Geof Sawaya
Como el OP solicitó Truecuando los valores son diferentes, la longitud del conjunto debe ser 2, no 1.
wombatonfire hace
@wombatonfire jaja buena captura. He ajustado mi respuesta de 7 años :)
roippi hace
Las buenas respuestas no envejecen :) Buen enfoque con un conjunto.
wombatonfire hace
7
>>> any([False, False, False])
False
>>> any([False, True, False])
True
>>> all([False, True, True])
False
>>> all([True, True, True])
True
Jobin
fuente
4
s = "eFdss"
s = list(s)
all(i.islower() for i in s )   # FALSE
any(i.islower() for i in s )   # TRUE
David Gladson
fuente
1

El concepto es simple:

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
fuente
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
fuente