¿Cómo probar múltiples variables contra un valor?

Estoy tratando de hacer una función que compare varias variables con un entero y genere una cadena de tres letras. Me preguntaba si había una manera de traducir esto a Python. Así que di:

x = 0 y = 1 z = 3 mylist = [] if x or y or z == 0 : mylist.append("c") if x or y or z == 1 : mylist.append("d") if x or y or z == 2 : mylist.append("e") if x or y or z == 3 : mylist.append("f") 

que devolvería una lista de

 ["c", "d", "f"] 

¿Es algo como esto posible?

Usted malinterpreta cómo funcionan las expresiones booleanas; no funcionan como una oración en inglés y supongo que estás hablando de la misma comparación para todos los nombres aquí. Estás buscando:

 if x == 1 or y == 1 or z == 1: 

y son evaluados por sí mismos ( False si 0 , True contrario).

Puedes acortar eso usando una prueba de contención contra una tupla :

 if 1 in (x, y, z): 

o mejor aún:

 if 1 in {x, y, z}: 

usar un set para aprovechar la prueba de membresía de costo constante ( in toma una cantidad fija de tiempo cualquiera que sea el operando de la izquierda).

Cuando usas or , python ve cada lado del operador como expresiones separadas . La expresión x or y == 1 se trata como una prueba booleana para x , luego, si eso es falso, se prueba la expresión y == 1 .

Esto se debe a la precedencia del operador . El operador or tiene una prioridad más baja que la prueba == , por lo que este último se evalúa primero .

Sin embargo, incluso si este no fuera el caso, y la expresión x or y or z == 1 realidad se interpretara como (x or y or z) == 1 lugar, esto no haría lo que se espera que haga.

x or y or z evaluarán el primer argumento que sea “veraz”, por ejemplo, no False , numérico 0 o vacío (consulte las expresiones booleanas para obtener información sobre lo que Python considera falso en un contexto booleano).

Así que para los valores x = 2; y = 1; z = 0 x = 2; y = 1; z = 0 x = 2; y = 1; z = 0 , x or y or z se resolvería en 2 , porque ese es el primer valor de tipo verdadero en los argumentos. Entonces 2 == 1 sería False , aunque y == 1 sería True .

Lo mismo se aplicaría a lo inverso; probando múltiples valores contra una sola variable; x == 1 or 2 or 3 fallarían por las mismas razones. Utilice x == 1 or x == 2 or x == 3 o x in {1, 2, 3} .

Su problema se resuelve más fácilmente con una estructura de diccionario como:

 x = 0 y = 1 z = 3 d = {0: 'c', 1:'d', 2:'e', 3:'f'} mylist = [d[k] for k in [x, y, z]] 

Solución anterior: según lo declarado por Martijn Pieters, el formato correcto y más rápido es:

 if 1 in {x, y, z}: 

El único problema importante que no parece solucionarse es que desea que su lista de salida incluya cada letra después de una statement de verdadero si.

Usando solo el consejo de Martijn Pieters, ahora tendrías:

 if 0 in {x, y, z}: Mylist.append("c") elif 1 in {x, y, z}: Mylist.append("d") ... 

Problema: la primera instrucción if devolvería verdadero, y nunca llegaría a la siguiente instrucción elif. Así que tu lista simplemente regresaría:

 ["c"] 

Lo que quieres es tener sentencias if separadas para que Python lea cada afirmación si la primera fue verdadera o falsa. Como:

 if 0 in {x, y, z}: Mylist.append("c") if 1 in {x, y, z}: Mylist.append("d") if 2 in {x, y, z}: Mylist.append("e") ... 

Esto funcionará, pero ‘si’ se siente cómodo usando diccionarios (vea lo que hice allí), puede limpiar esto haciendo un diccionario inicial que asigne los números a las letras que desea, y luego simplemente use un bucle ‘for’:

 numToLetters = {0:"c", 1:"d", 2:"e", 3:"f"} for number in numToLetters: if number in {x, y, z}: Mylist.append(numToLetters[number]) 

La forma directa de escribir x or y or z == 0 es

 if any(map((lambda value: value == 0), (x,y,z))): pass # write your logic. 

Pero no creo, te guste. 🙂 Y esta manera es fea.

La otra forma (una mejor) es:

 0 in (x, y, z) 

Por cierto un montón de if s podría escribirse como algo como esto

 my_cases = { 0: Mylist.append("c"), 1: Mylist.append("d") # .. } for key in my_cases: if key in (x,y,z): my_cases[key]() break 

Si eres muy perezoso, puedes poner los valores dentro de una matriz. Como

 list = [] list.append(x) list.append(y) list.append(z) nums = [add numbers here] letters = [add corresponding letters here] for index in range(len(nums)): for obj in list: if obj == num[index]: MyList.append(letters[index]) break 

También puedes poner los números y las letras en un diccionario y hacerlo, pero esto probablemente sea MUCHO más complicado que simplemente las declaraciones. Eso es lo que obtienes por tratar de ser más perezoso 🙂

Una cosa más, tu

 if x or y or z == 0: 

Se comstackrá, pero no de la manera que usted quiere. Cuando simplemente pones una variable en una sentencia if (ejemplo)

 if b 

El progtwig comprobará si la variable no es nula. Otra forma de escribir la statement anterior (que tiene más sentido) es

 if bool(b) 

Bool es una función incorporada en python que básicamente realiza el comando de verificar una statement booleana (si no sabe qué es eso, es lo que está tratando de hacer en su statement if en este momento :))

Otra forma perezosa que encontré es:

 if any([x==0, y==0, z==0]) 

Para verificar si un valor está contenido dentro de un conjunto de variables, puede usar los módulos incorporados itertools y el operator .

Por ejemplo:

Importaciones:

 from itertools import repeat from operator import contains 

Declarar variables:

 x = 0 y = 1 z = 3 

Crea mapeo de valores (en el orden que quieras verificar):

 check_values = (0, 1, 3) 

Usa itertools para permitir la repetición de las variables:

 check_vars = repeat((x, y, z)) 

Finalmente, use la función de map para crear un iterador:

 checker = map(contains, check_vars, check_values) 

Luego, al verificar los valores (en el orden original), use next() :

 if next(checker) # Checks for 0 # Do something pass elif next(checker) # Checks for 1 # Do something pass 

etc …

Esto tiene una ventaja sobre la lambda x: x in (variables) porque el operator es un módulo incorporado y es más rápido y más eficiente que usar lambda que tiene que crear una función personalizada en el lugar.

Otra opción para verificar si hay un valor distinto de cero (o Falso) en una lista:

 not (x and y and z) 

Equivalente:

 not all((x, y, z)) 

Creo que esto lo manejará mejor:

 my_dict = {0: "c", 1: "d", 2: "e", 3: "f"} def validate(x, y, z): for ele in [x, y, z]: if ele in my_dict.keys(): return my_dict[ele] 

Salida:

 print validate(0, 8, 9) c print validate(9, 8, 9) None print validate(9, 8, 2) e