Estou escrevendo um sistema de segurança que nega o acesso a usuários não 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.")
Ele concede acesso a usuários autorizados conforme o esperado, mas também permite a entrada de usuários não autorizados!
Hello. Please enter your name:
Bob
Access granted.
Por que isso ocorre? Afirmei claramente que só concedo acesso quando for name
igual a Kevin, Jon ou Inbar. Também tentei a lógica oposta if "Kevin" or "Jon" or "Inbar" == name
, mas o resultado é o mesmo.
python
boolean
boolean-expression
Kevin
fonte
fonte
x or y in z
,x and y in z
,x != y and z
e alguns outros. Embora não seja exatamente idêntica a esta pergunta, a causa raiz é a mesma para todas elas. Só queria salientar isso, caso alguém tenha fechado sua pergunta como uma duplicata desta e não tenha certeza de como isso é relevante para eles.Respostas:
Em muitos casos, Python se parece e se comporta como o inglês natural, mas este é um caso em que essa abstração falha. As pessoas podem usar pistas de contexto para determinar que "Jon" e "Inbar" são objetos unidos ao verbo "igual a", mas o interpretador Python é mais literal.
é logicamente equivalente a:
O que, para o usuário Bob, é equivalente a:
O
or
operador escolhe o primeiro argumento com um valor verdade positivo :E como "Jon" tem um valor verdadeiro positivo, o
if
bloco é executado. Isso é o que faz com que "Acesso concedido" seja impresso independentemente do nome fornecido.Todo esse raciocínio também se aplica à expressão
if "Kevin" or "Jon" or "Inbar" == name
. o primeiro valor"Kevin"
,, é verdadeiro, então oif
bloco é executado.Existem duas maneiras comuns de construir adequadamente esta condicional.
Use vários
==
operadores para verificar explicitamente cada valor:if name == "Kevin" or name == "Jon" or name == "Inbar":
Componha uma sequência de valores válidos e use o
in
operador para testar a associação:if name in {"Kevin", "Jon", "Inbar"}:
Em geral dos dois, o segundo deve ser o preferido, pois é mais fácil de ler e também mais rápido:
Para aqueles que podem querer uma prova de que
if a == b or c or d or e: ...
é realmente analisado assim. Oast
módulo integrado fornece uma resposta:Portanto, o
test
daif
declaração é assim:Como se pode ver, é o operador booleano
or
aplicada a múltiplosvalues
, ou seja,a == b
ec
,d
ee
.fonte
("Kevin", "Jon", "Inbar")
vez de um conjunto{"Kevin", "Jon", "Inbar"}
?a in {b, c, d}
é duas vezes mais rápido do quea in (b, c, d)
na minha máquina. Algo para se pensar se este é um código de desempenho crítico.frozenset
vez disso, o torna uma , de modo que a sobrecarga do conjunto de construção não está lá.dis.dis(compile("1 in {1, 2, 3}", '<stdin>', 'eval'))
Problema de engenharia simples, vamos um pouco mais longe.
Mas, herdado da linguagem C, Python avalia o valor lógico de um inteiro diferente de zero como True.
Agora, Python se baseia nessa lógica e permite que você use literais lógicos, como ou em inteiros, e assim
Finalmente
A maneira correta de escrever seria:
Por segurança, eu também sugiro que você não codifique senhas.
fonte
Existem 3 verificações de condições
if name == "Kevin" or "Jon" or "Inbar":
e esta declaração if é equivalente a
Visto
elif "Jon"
que sempre será verdadeiro, o acesso a qualquer usuário é concedidoSolução
Você pode usar qualquer um dos métodos abaixo
Rápido
Lento
Código lento + desnecessário
fonte