J'écris un système de sécurité qui refuse l'accès aux utilisateurs non autorisés.
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.")
Il accorde l'accès aux utilisateurs autorisés comme prévu, mais il permet également aux utilisateurs non autorisés!
Hello. Please enter your name:
Bob
Access granted.
Pourquoi cela se produit-il? J'ai clairement déclaré de n'accorder l'accès que lorsque c'est name
égal à Kevin, Jon ou Inbar. J'ai aussi essayé la logique inverse if "Kevin" or "Jon" or "Inbar" == name
, mais le résultat est le même.
x or y in z
,x and y in z
,x != y and z
et quelques autres. Bien qu'elle ne soit pas exactement identique à cette question, la cause première est la même pour tous. Je voulais juste le signaler au cas où quelqu'un aurait fermé sa question comme un double et ne serait pas sûr de sa pertinence pour lui.Réponses:
Dans de nombreux cas, Python ressemble et se comporte comme un anglais naturel, mais c'est un cas où cette abstraction échoue. Les gens peuvent utiliser des indices de contexte pour déterminer que «Jon» et «Inbar» sont des objets joints au verbe «égal», mais l'interpréteur Python est plus littéral.
équivaut logiquement à:
Ce qui, pour l'utilisateur Bob, équivaut à:
L'
or
opérateur choisit le premier argument avec une valeur de vérité positive :Et comme "Jon" a une valeur de vérité positive, le
if
bloc s'exécute. C'est ce qui provoque l'impression de "Accès accordé" quel que soit le nom donné.Tout ce raisonnement s'applique également à l'expression
if "Kevin" or "Jon" or "Inbar" == name
. la première valeur"Kevin"
,, est vraie, donc leif
bloc s'exécute.Il existe deux façons courantes de construire correctement ce conditionnel.
Utilisez plusieurs
==
opérateurs pour vérifier explicitement chaque valeur:if name == "Kevin" or name == "Jon" or name == "Inbar":
Composez une séquence de valeurs valides et utilisez l'
in
opérateur pour tester l'appartenance:if name in {"Kevin", "Jon", "Inbar"}:
En général, le second devrait être préféré car il est plus facile à lire et aussi plus rapide:
Pour ceux qui veulent une preuve qui
if a == b or c or d or e: ...
est en effet analysée comme ça. Least
module intégré fournit une réponse:Ainsi , le
test
desif
états se présente comme suit:Comme on peut le voir, il est l'opérateur booléen
or
appliqué à plusieursvalues
, à savoir,a == b
etc
,d
ete
.la source
("Kevin", "Jon", "Inbar")
au lieu d'un ensemble{"Kevin", "Jon", "Inbar"}
?a in {b, c, d}
est environ deux fois plus rapide quea in (b, c, d)
sur ma machine. Quelque chose à penser s'il s'agit d'un morceau de code critique pour les performances.frozenset
place, de sorte que la surcharge de l'ensemble de construction n'est pas là.dis.dis(compile("1 in {1, 2, 3}", '<stdin>', 'eval'))
Problème d'ingénierie simple, allons simplement un peu plus loin.
Mais, hérité du langage C, Python évalue la valeur logique d'un entier non nul comme True.
Maintenant, Python s'appuie sur cette logique et vous permet d'utiliser des littéraux logiques tels que ou sur des entiers, etc.
finalement
La bonne façon de l'écrire serait:
Pour plus de sécurité, je vous suggère également de ne pas coder en dur les mots de passe.
la source
Il y a 3 contrôles de condition
if name == "Kevin" or "Jon" or "Inbar":
et cette instruction if équivaut à
Puisque
elif "Jon"
sera toujours vrai, l'accès à n'importe quel utilisateur est accordéSolution
Vous pouvez utiliser l'une des méthodes ci-dessous
Vite
Lent
Code lent + inutile
la source