Estoy escribiendo un sistema de seguridad que niega el acceso a usuarios no autorizados.
import sys
print("Hello. Please enter your name:")
name = sys.stdin.readline().strip()
if name == "Kevin" or "Jon" or "Inbar":
print("Access granted.")
else:
print("Access denied.")
Otorga acceso a usuarios autorizados como se esperaba, ¡pero también permite la entrada de usuarios no autorizados!
Hello. Please enter your name:
Bob
Access granted.
¿Por qué ocurre esto? He dicho claramente que solo otorgaré acceso cuando sea name
igual a Kevin, Jon o Inbar. También he probado la lógica opuesta if "Kevin" or "Jon" or "Inbar" == name
, pero el resultado es el mismo.
x or y in z
,x and y in z
,x != y and z
y algunos otros. Si bien no es exactamente idéntico a esta pregunta, la causa raíz es la misma para todos ellos. Solo quería señalar eso en caso de que alguien cerrara su pregunta como un duplicado de esto y no estuviera seguro de cómo es relevante para ellos.Respuestas:
En muchos casos, Python se ve y se comporta como el inglés natural, pero este es un caso en el que falla esa abstracción. La gente puede usar pistas de contexto para determinar que "Jon" e "Inbar" son objetos unidos al verbo "igual", pero el intérprete de Python tiene una mentalidad más literal.
es lógicamente equivalente a:
Lo que, para el usuario Bob, equivale a:
El
or
operador elige el primer argumento con un valor de verdad positivo :Y dado que "Jon" tiene un valor de verdad positivo, el
if
bloque se ejecuta. Eso es lo que hace que se imprima "Acceso concedido" independientemente del nombre dado.Todo este razonamiento también se aplica a la expresión
if "Kevin" or "Jon" or "Inbar" == name
. el primer valor"Kevin"
,, es verdadero, por lo que elif
bloque se ejecuta.Hay dos formas comunes de construir correctamente este condicional.
Utilice varios
==
operadores para comprobar explícitamente cada valor:if name == "Kevin" or name == "Jon" or name == "Inbar":
Componga una secuencia de valores válidos y use el
in
operador para probar la pertenencia:if name in {"Kevin", "Jon", "Inbar"}:
En general, de los dos, debería preferirse el segundo, ya que es más fácil de leer y también más rápido:
Para aquellos que quieran una prueba de que de
if a == b or c or d or e: ...
hecho se analiza así. Elast
módulo integrado proporciona una respuesta:Entonces, el
test
de laif
declaración se ve así:Como se puede ver, es el operador booleano
or
aplica a múltiplesvalues
, a saber,a == b
yc
,d
, ye
.fuente
("Kevin", "Jon", "Inbar")
lugar de un conjunto{"Kevin", "Jon", "Inbar"}
?a in {b, c, d}
es aproximadamente el doble de rápido quea in (b, c, d)
en mi máquina. Algo en lo que pensar si se trata de una pieza de código crítica para el rendimiento.frozenset
, por lo que la sobrecarga del conjunto de construcción no está allí.dis.dis(compile("1 in {1, 2, 3}", '<stdin>', 'eval'))
Problema de ingeniería simple, simplemente vayamos un poco más lejos.
Pero, heredado del lenguaje C, Python evalúa el valor lógico de un entero distinto de cero como Verdadero.
Ahora, Python se basa en esa lógica y le permite usar literales lógicos como o sobre enteros, y así
Finalmente
La forma correcta de escribirlo sería:
Por seguridad, también te sugiero que no codifiques las contraseñas.
fuente
Hay 3 comprobaciones de estado en
if name == "Kevin" or "Jon" or "Inbar":
y esta declaración if es equivalente a
Dado
elif "Jon"
que siempre será cierto por lo que se concede acceso a cualquier usuarioSolución
Puede utilizar cualquiera de los métodos siguientes
Rápido
Lento
Código lento + innecesario
fuente