vacia una rangos lista len función funcion for example establecer español elementos crear bitwise agregar python numpy bit-manipulation boolean-expression ampersand

una - Diferencia entre ''y''(booleano) vs. ''&''(bitwise) en python. ¿Por qué diferencia en el comportamiento con listas vs matrices numpy?



funcion len python (7)

Acerca de la list

Primero, un punto muy importante, del cual todo seguirá (espero).

En Python ordinario, la list no es especial de ninguna manera (excepto que tiene una linda sintaxis para construir, que es principalmente un accidente histórico). Una vez que se hace una lista [3,2,6] , es para todos los efectos un objeto ordinario de Python, como un número 3 , un conjunto {3,7} o una función lambda x: x+5 .

(Sí, admite el cambio de sus elementos, y es compatible con la iteración, y muchas otras cosas, pero eso es exactamente lo que es un tipo: admite algunas operaciones, mientras que no admite otras. Int soporta subir a una potencia, pero eso no hazlo muy especial, es solo lo que es una int. lambda admite llamadas, pero eso no lo hace muy especial, para eso es para lo que es lambda :).

Sobre and

and no es un operador (puede llamarlo "operador", pero también puede llamar "a" un operador :). Los operadores en Python son (implementados a través de) métodos llamados a objetos de algún tipo, generalmente escritos como parte de ese tipo. No hay forma de que un método tenga una evaluación de algunos de sus operandos, pero puede (y debe) hacerlo.

La consecuencia de eso es que no se puede sobrecargar y no se puede sobrecargar. Es completamente general y se comunica a través de un protocolo específico. Lo que puedes hacer es personalizar tu parte del protocolo, pero eso no significa que puedas alterar completamente el comportamiento. El protocolo es:

Imagine Python interpretando "a y b" (esto no sucede literalmente de esta manera, pero ayuda a la comprensión). Cuando se trata de "y", mira el objeto que acaba de evaluar (a) y le pregunta: ¿es cierto? ( NO : ¿es True ?) Si usted es autor de una clase, puede personalizar esta respuesta. Si a responde "no", and (omite b completamente, no se evalúa en absoluto, y) dice: a es mi resultado ( NO : falso es mi resultado).

Si a no responde, and pregunta: ¿cuál es su longitud? (De nuevo, puedes personalizar esto como autor de a clase). Si a responde 0, and hace lo mismo que arriba, lo considera falso ( NO falso), omite b y da como resultado.

Si responde algo que no sea 0 a la segunda pregunta ("¿cuál es su longitud"), o no responde en absoluto, o responde "sí" al primero ("¿es cierto?"), and evalúa b , y dice: b es mi resultado. Tenga en cuenta que NO formula ninguna pregunta.

La otra forma de decir todo esto es que a and b es casi lo mismo que b if a else a , excepto a, se evalúa solo una vez.

Ahora siéntese unos minutos con un lápiz y papel, y convénzase de que cuando {a, b} es un subconjunto de {True, False}, funciona exactamente como se esperaría de los operadores booleanos. Pero espero haberte convencido de que es mucho más general, y como verás, mucho más útil de esta manera.

Poniendo esos dos juntos

Ahora espero que comprenda su ejemplo 1. and no le importa si mylist1 es un número, lista, lambda o un objeto de una clase Argmhbl. Simplemente se preocupa por la respuesta de mylist1 a las preguntas del protocolo. Y, por supuesto, mylist1 responde 5 a la pregunta sobre la longitud, por lo que devuelve mylist2. Y eso es. No tiene nada que ver con los elementos de mylist1 y mylist2; no entran en ninguna parte de la imagen.

Segundo ejemplo: & en la list

Por otro lado, & es un operador como cualquier otro, como + por ejemplo. Se puede definir para un tipo definiendo un método especial en esa clase. int define como "y" a nivel de bit, y bool lo define como "y" lógico, pero esa es solo una opción: por ejemplo, los conjuntos y algunos otros objetos como las vistas de claves dict lo definen como una intersección de conjunto. list simplemente no lo define, probablemente porque Guido no pensó en ninguna forma obvia de definirlo.

numpy

En la otra pierna: -D, las matrices numpy son especiales, o al menos están intentando serlo. Por supuesto, numpy.array es solo una clase, no puede anular and de ninguna manera, por lo que hace la siguiente mejor opción: cuando se le pregunta "¿eres cierto?", Numpy.array levanta un ValueError, diciendo "por favor, reformula la pregunta, mi visión de la verdad no encaja en tu modelo ". (Tenga en cuenta que el mensaje ValueError no habla sobre and - porque numpy.array no sabe quién le hace la pregunta, solo habla de la verdad).

Para & , es una historia completamente diferente. numpy.array puede definirlo como lo desee, y define & consistentemente con otros operadores: puntualmente. Así que finalmente obtienes lo que quieres.

HTH,

¿Qué explica la diferencia en el comportamiento de las operaciones booleanas y bit a bit en las listas frente a numpy.arrays?

Me confunde el uso apropiado de '' & '' vs '' and '' en python, ilustrado en los siguientes ejemplos simples.

mylist1 = [True, True, True, False, True] mylist2 = [False, True, False, True, False] >>> len(mylist1) == len(mylist2) True # ---- Example 1 ---- >>>mylist1 and mylist2 [False, True, False, True, False] #I am confused: I would have expected [False, True, False, False, False] # ---- Example 2 ---- >>>mylist1 & mylist2 *** TypeError: unsupported operand type(s) for &: ''list'' and ''list'' #I am confused: Why not just like example 1? # ---- Example 3 ---- >>>import numpy as np >>> np.array(mylist1) and np.array(mylist2) *** ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all() #I am confused: Why not just like Example 4? # ---- Example 4 ---- >>> np.array(mylist1) & np.array(mylist2) array([False, True, False, False, False], dtype=bool) #This is the output I was expecting!

Esta answer y esta answer me ayudaron a entender que ''and'' es una operación booleana, pero ''&'' es una operación bit a bit.

Estaba reading cierta información para comprender mejor el concepto de reading , pero estoy luchando por usar esa información para dar sentido a mis 4 ejemplos anteriores.

Tenga en cuenta que, en mi situación particular, mi resultado deseado es una nueva lista donde:

len(newlist) == len(mylist1) newlist[i] == (mylist1[i] and mylist2[i]) #for every element of newlist

El ejemplo 4, anterior, me llevó a la salida deseada, así que está bien.

Pero me siento confundido sobre cuándo / cómo / por qué debería usar ''y'' vs ''&''. ¿Por qué las listas y matrices numpy se comportan de manera diferente con estos operadores?

¿Alguien puede ayudarme a entender la diferencia entre las operaciones booleanas y bit a bit para explicar por qué manejan las listas y numpy.arrays de manera diferente?

Solo quiero asegurarme de continuar usando estas operaciones correctamente en el futuro. ¡Muchas gracias por la ayuda!

Numpy version 1.7.1 python 2.7 References all inline with text.

EDITS

1) Gracias @delnan por señalar que en mis ejemplos originales tenía una ambigüedad que estaba enmascarando mi confusión más profunda. He actualizado mis ejemplos para aclarar mi pregunta.


  1. En Python, una expresión de X and Y devuelve Y , dado que bool(X) == True o cualquiera de X o Y evalúa como False, por ejemplo:

    True and 20 >>> 20 False and 20 >>> False 20 and [] >>> []

  2. El operador bit a bit simplemente no está definido para las listas. Pero está definido para enteros: opera sobre la representación binaria de los números. Considere 16 (01000) y 31 (11111):

    16 & 31 >>> 16

  3. NumPy no es un psíquico, no sabe, si quiere decir que, por ejemplo, [False, False] debería ser igual a True en una expresión lógica. En esto, anula un comportamiento estándar de Python, que es: "Cualquier colección vacía con len(collection) == 0 es False ".

  4. Probablemente un comportamiento esperado de las matrices y el operador de NumPy.


Las operaciones con una lista de Python operan en la lista . list1 and list2 verificará si list1 está vacío, y devuelve list1 si es, y list2 si no lo está. list1 + list2 anexará list2 a list1 , por lo que obtendrá una nueva lista con elementos len(list1) + len(list2) .

Los operadores que solo tienen sentido cuando se aplican a elementos, como & , TypeError un TypeError , ya que las operaciones de elementos no son compatibles sin pasar por los elementos.

Las matrices Numpy admiten operaciones de elemento . array1 & array2 calcularán el bit a bit o para cada elemento correspondiente en array1 y array2 . array1 + array2 calculará la suma de cada elemento correspondiente en array1 y array2 .

Esto no funciona para and y or .

array1 and array2 es esencialmente una abreviatura para el siguiente código:

if bool(array1): return array2 else: return array1

Para esto necesitas una buena definición de bool(array1) . Para operaciones globales como las usadas en las listas de Python, la definición es que bool(list) == True si la list no está vacía, y False si está vacía. Para las operaciones numpy en cuanto a los elementos, existe cierta desajuste entre comprobar si algún elemento se evalúa como True o si todos los elementos se evalúan como True . Como ambos son discutiblemente correctos, Numpy no adivina y genera un ValueError cuando bool() se ValueError (indirectamente) en una matriz.


Los operadores booleanos en cortocircuito ( and , or ) no se pueden anular porque no hay una manera satisfactoria de hacerlo sin introducir nuevas funciones de lenguaje o sacrificar el cortocircuito. Como puede o no puede saber, evalúan el primer operando por su valor de verdad, y dependiendo de ese valor, evalúan y devuelven el segundo argumento, o no evalúan el segundo argumento y devuelven el primero:

something_true and x -> x something_false and x -> something_false something_true or x -> something_true something_false or x -> x

Tenga en cuenta que se devuelve el (resultado de evaluar el) operando real, no el valor de verdad del mismo.

La única forma de personalizar su comportamiento es anular __nonzero__ (renombrado a __bool__ en Python 3), por lo que puede afectar qué operando se devuelve, pero no devolver algo diferente. Las listas (y otras colecciones) se definen como "verdaderas" cuando contienen algo y "falsey" cuando están vacías.

Los arreglos NumPy rechazan esa noción: para los casos de uso a los que apuntan, dos nociones diferentes de verdad son comunes: (1) Si cualquier elemento es verdadero, y (2) si todos los elementos son verdaderos. Dado que estos dos son completamente (y silenciosamente) incompatibles, y ninguno es claramente más correcto o más común, NumPy se niega a adivinar y requiere que use explícitamente .any() o .all() .

& y | (y not , por cierto) puede ser anulado por completo, ya que no cortocircuitan. Pueden devolver cualquier cosa cuando se les reemplaza, y NumPy hace un buen uso de eso para hacer operaciones de elementos, como lo hacen con prácticamente cualquier otra operación escalar. Las listas, por otro lado, no transmiten operaciones a través de sus elementos. Así como mylist1 - mylist2 no significa nada y mylist1 + mylist2 significa algo completamente diferente, no hay un operador para las listas.


Para el primer ejemplo y base en el documento de django
Siempre devolverá la segunda lista, de hecho, una lista no vacía se ve como un valor verdadero para Python, por lo que Python devuelve el "último" valor verdadero para que la segunda lista

In [74]: mylist1 = [False] In [75]: mylist2 = [False, True, False, True, False] In [76]: mylist1 and mylist2 Out[76]: [False, True, False, True, False] In [77]: mylist2 and mylist1 Out[77]: [False]


and prueba si ambas expresiones son lógicamente True mientras que & (cuando se usa con valores True / False ) prueba si ambas son True .

En Python, los objetos incorporados vacíos suelen tratarse como lógicamente False mientras que los incorporados no vacíos son lógicamente True . Esto facilita el caso de uso común en el que desea hacer algo si una lista está vacía y otra cosa si la lista no lo está. Tenga en cuenta que esto significa que la lista [False] es lógicamente True :

>>> if [False]: ... print ''True'' ... True

Entonces, en el Ejemplo 1, la primera lista no está vacía y, por lo tanto, es lógicamente True , por lo que el valor de verdad de and es el mismo que el de la segunda lista. (En nuestro caso, la segunda lista no está vacía y, por lo tanto, es lógicamente True , pero identificarla requeriría un paso de cálculo innecesario).

Por ejemplo, 2, las listas no se pueden combinar significativamente en una forma bit a bit porque pueden contener elementos arbitrarios a diferencia. Las cosas que se pueden combinar en bits incluyen: Trues y Falses, enteros.

Los objetos NumPy, por el contrario, admiten cálculos vectorizados. Es decir, te permiten realizar las mismas operaciones en múltiples piezas de datos.

El ejemplo 3 falla porque las matrices NumPy (de longitud> 1) no tienen ningún valor de verdad ya que esto evita la confusión de la lógica basada en vectores.

El ejemplo 4 es simplemente un bit and operación vectorizados.

Línea de fondo

  • Si no está tratando con matrices y no está realizando manipulaciones matemáticas de enteros, probablemente desee and .

  • Si tiene vectores de valores de verdad que desea combinar, use numpy con & .


Ejemplo 1:

Así es como funciona el operador ''and'' .

x y y => si x es falso, luego x , else y

En otras palabras, dado que mylist1 no es False , el resultado de la expresión es mylist2 . (Solo las listas vacías se evalúan como False ).

Ejemplo 2:

El operador & es para un bit a bit y, como usted menciona. Las operaciones a nivel de bit solo funcionan en números. El resultado de a & b es un número compuesto por 1s en bits que son 1 en a y b . Por ejemplo:

>>> 3 & 1 1

Es más fácil ver lo que sucede con un literal binario (los mismos números que arriba):

>>> 0b0011 & 0b0001 0b0001

Las operaciones bit a bit son similares en concepto a las operaciones booleanas (verdad), pero funcionan solo en bits.

Entonces, dado un par de declaraciones sobre mi auto

  1. Mi coche es rojo
  2. Mi auto tiene ruedas

El "y" lógico de estas dos afirmaciones es:

(¿mi auto está rojo?) y (¿el coche tiene ruedas?) => lógico verdadero de falso valor

Ambas son ciertas, al menos para mi auto. Entonces el valor del enunciado como un todo es lógicamente verdadero.

El "y" bit a bit de estas dos afirmaciones es un poco más nebuloso:

(el valor numérico de la afirmación "mi automóvil es rojo") & (el valor numérico de la declaración "mi automóvil tiene ruedas") => número

Si python sabe cómo convertir los enunciados a valores numéricos, entonces lo hará y calculará el bit a bit y los dos valores. Esto puede llevarte a creer que & es intercambiable con and , pero como en el ejemplo anterior, son cosas diferentes. Además, para los objetos que no se pueden convertir, obtendrá un TypeError .

Ejemplo 3 y 4:

Numpy implementa operaciones aritméticas para matrices:

Las operaciones aritméticas y de comparación en ndarrays se definen como operaciones de elementos, y generalmente dan como resultado resultados de objetos ndarray.

Pero no implementa operaciones lógicas para matrices, porque no puede sobrecargar operadores lógicos en Python . Es por eso que el ejemplo tres no funciona, pero el ejemplo cuatro sí.

Entonces para responder a su and vs & pregunta: Use and .

Las operaciones en modo bit se utilizan para examinar la estructura de un número (qué bits se establecen, qué bits no se establecen). Este tipo de información se usa principalmente en interfaces de sistema operativo de bajo nivel ( bits de permisos de Unix , por ejemplo). La mayoría de los programas de Python no necesitarán saber eso.

Las operaciones lógicas ( and , or , not ), sin embargo, se usan todo el tiempo.