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

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

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

d es 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 salir

 # [False, True, False] 

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

¿Por qué se evalúa a Falso para todas las tuplas?

A grandes rasgos, puede pensar en any y all como series de operadores lógicos y and , respectivamente.

alguna

any devolverá True cuando al menos uno de los elementos sea ​​Verdadero. Lea acerca de las pruebas de valor de verdad.

todos

all volverá True solo cuando todos los elementos sean verdaderos.

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 este

any

Devuelva True si cualquier elemento de lo iterable es true. Si el iterable está vacío, devuelve False

Como ninguno de los elementos es verdadero, devuelve False en este caso.

all

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

Como ninguno de los elementos es falso, devuelve True en este caso.


Nota 2:

Otra cosa importante que se debe saber acerca de any y all , es que causará un corto circuito en la ejecución, en el momento en que se conozca el resultado. La ventaja es que todo iterable no necesita ser consumido. 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)) es una expresión generadora que devuelve True si el número actual entre 1 y 9 es un múltiplo de 6. any itera los multiples_of_6 de_6 y cuando cumple con 6 , encuentra un valor de True , por lo que inmediatamente devuelve True , y el rest de los multiples_of_6 no se itera. Eso es lo que vemos cuando imprimimos la list(multiples_of_6) , el resultado de 7 , 8 y 9 .

Esta excelente cosa se usa muy inteligentemente en esta respuesta .


Con este entendimiento básico, si miramos su código, usted hace

 any(x) and not all(x) 

lo que asegura que, al menos uno de los valores es Verdad, pero no todos. Es por eso que está devolviendo [False, False, False] . Si realmente quisieras comprobar si ambos números no son los mismos,

 print [x[0] != x[1] for x in zip(*d['Drd2'])] 

¿Cómo funcionan all y all funciones de Python?

any y all toman iterables y devuelven True si 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, any devuelve False , y all devuelven True .

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

Estaba demostrando all para los estudiantes en clase hoy. En su mayoría estaban confundidos acerca de los valores de retorno para los iterables vacíos. Explicarlo de esta manera provocó que muchas bombillas se encendieran.

Comportamiento abreviado

Ellos, any y all , buscan una condición que les permita dejar de evaluar. Los primeros ejemplos que les di requerían que evaluaran el booleano para cada elemento de la lista completa.

(Tenga en cuenta que la lista literal no se evalúa perezosamente, podría obtenerla con un iterador , pero esto es solo con 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 tienen mucho más rendimiento, pero puede sustituir lo anterior y obtener los mismos resultados para el código en esta (o cualquier otra) respuesta.

all

all comprobaciones para que los elementos sean False (para que pueda devolver False ), luego devuelve True si ninguno de ellos era 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 funciona es que comprueba que los elementos sean True (para que puedan devolverlos True), then it returns Falso if none of them were Verdadero.

 >>> 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 tienes en cuenta el comportamiento de corte corto, entenderás intuitivamente cómo funcionan sin tener que hacer referencia a una Tabla de verdad.

Evidencia de all y any atajo:

Primero, crea un noisy_iterator:

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

y ahora vamos a iterar sobre 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 all paradas en el primer cheque booleano falso.

Y any parada en el primer cheque booleano verdadero:

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

El código en cuestión que estás preguntando proviene de mi respuesta que se da aquí . Fue pensado para resolver el problema de comparar múltiples arreglos de bits, es decir, colecciones de 1 y 0 .

all y all son útiles cuando se puede confiar en la “veracidad” de los valores, es decir, su valor en un contexto booleano. 1 es True y 0 es False , una conveniencia que esa respuesta aprovechó. Sucede que 5 también es True , así que cuando lo mezcles en tus posibles entradas … bueno. No funciona

Podrías hacer algo como esto:

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

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

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 estos 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 que no haya cortocircuitos.

Cuando Guido van Rossum (el creador de Python) propuso por primera vez la adición de any() y all() , los explicó simplemente publicando exactamente los fragmentos de código anteriores.

 >>> any([False, False, False]) False >>> any([False, True, False]) True >>> all([False, True, True]) False >>> all([True, True, True]) True 
 s = "eFdss" s = list(s) all(i.islower() for i in s ) # FALSE any(i.islower() for i in s ) # TRUE 

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