Kev*_*vin 96 python boolean boolean-expression
我正在编写一个拒绝访问未授权用户的安全系统.
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.")
Run Code Online (Sandbox Code Playgroud)
它按预期授予对授权用户的访问权限,但它也允许未经授权的用户访问!
Hello. Please enter your name:
Bob
Access granted.
Run Code Online (Sandbox Code Playgroud)
为什么会这样?我明确表示,只有在与nameKevin,Jon或Inbar相同时才授予访问权限.我也尝试过相反的逻辑if "Kevin" or "Jon" or "Inbar" == name,但结果是一样的.
Kev*_*vin 134
在许多情况下,Python的外观和行为与自然英语相似,但这是抽象失败的一种情况.人们可以使用上下文线索来确定"Jon"和"Inbar"是加入动词"equals"的对象,但Python解释器更具有文字意识.
if name == "Kevin" or "Jon" or "Inbar":
Run Code Online (Sandbox Code Playgroud)
在逻辑上等同于:
if (name == "Kevin") or ("Jon") or ("Inbar"):
Run Code Online (Sandbox Code Playgroud)
对于用户Bob来说,相当于:
if (False) or ("Jon") or ("Inbar"):
Run Code Online (Sandbox Code Playgroud)
该or运营商选择以积极的第一个参数真值:
if ("Jon"):
Run Code Online (Sandbox Code Playgroud)
由于"Jon"具有正的真值,因此该if块执行.这就是导致"授予访问权限"被打印的原因,无论给出的名称如何.
所有这些推理也适用于表达式if "Kevin" or "Jon" or "Inbar" == name.第一个值为"Kevin"true,因此if块执行.
有两种常用方法可以正确构建此条件.
使用多个==运算符显式检查每个值:
if name == "Kevin" or name == "Jon" or name == "Inbar":
编写一系列有效值,并使用in运算符测试成员资格:
if name in {"Kevin", "Jon", "Inbar"}:
一般来说,第二个应该是首选,因为它更容易阅读,也更快:
>>> import timeit
>>> timeit.timeit('name == "Kevin" or name == "Jon" or name == "Inbar"', setup="name='Inbar'")
0.4247764749999945
>>> timeit.timeit('name in {"Kevin", "Jon", "Inbar"}', setup="name='Inbar'")
0.18493307199999265
Run Code Online (Sandbox Code Playgroud)
if name == "Kevin" or "Jon" or "Inbar":
Run Code Online (Sandbox Code Playgroud)
逻辑上等价于:
if (name == "Kevin") or ("Jon") or ("Inbar"):
Run Code Online (Sandbox Code Playgroud)
对于用户 Bob 来说,这相当于:
if (False) or ("Jon") or ("Inbar"):
Run Code Online (Sandbox Code Playgroud)
注意:Python 将任何非零整数的逻辑值计算为True。因此,所有非空列表、集合、字符串等都是可计算的并返回True
运算or符选择第一个具有正真值的参数。
因此,“Jon”具有正真值并且 if 块执行,因为它现在相当于
if (False) or (True) or (True):
Run Code Online (Sandbox Code Playgroud)
这就是导致无论输入什么名称都会打印“授予访问权限”的原因。
解决方案 1:使用多个==运算符显式检查每个值
if name == "Kevin" or name == "Jon" or name == "Inbar":
print("Access granted.")
else:
print("Access denied.")
Run Code Online (Sandbox Code Playgroud)
解决方案 2:组合有效值的集合(例如集合、列表或元组),并使用运算in符来测试成员资格(更快,首选方法)
if name in {"Kevin", "Jon", "Inbar"}:
print("Access granted.")
else:
print("Access denied.")
Run Code Online (Sandbox Code Playgroud)
或者
if name in ["Kevin", "Jon", "Inbar"]:
print("Access granted.")
else:
print("Access denied.")
Run Code Online (Sandbox Code Playgroud)
解决方案 3:使用基本(且不是很有效)的 if-elif-else结构
if name == "Kevin":
print("Access granted.")
elif name == "Jon":
print("Access granted.")
elif name == "Inbar":
print("Access granted.")
else:
print("Access denied.")
Run Code Online (Sandbox Code Playgroud)
有 3 个条件检查if name == "Kevin" or "Jon" or "Inbar":
这个 if 语句相当于
if name == "Kevin":
print("Access granted.")
elif "Jon":
print("Access granted.")
elif "Inbar":
print("Access granted.")
else:
print("Access denied.")
Run Code Online (Sandbox Code Playgroud)
由于elif "Jon"始终为真,因此授予任何用户访问权限
您可以使用以下任意一种方法
快速地
if name in ["Kevin", "Jon", "Inbar"]:
print("Access granted.")
else:
print("Access denied.")
Run Code Online (Sandbox Code Playgroud)
慢的
if name == "Kevin" or name == "Jon" or name == "Inbar":
print("Access granted.")
else:
print("Access denied.")
Run Code Online (Sandbox Code Playgroud)
缓慢 + 不必要的代码
if name == "Kevin":
print("Access granted.")
elif name == "Jon":
print("Access granted.")
elif name == "Inbar":
print("Access granted.")
else:
print("Access denied.")
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
17734 次 |
| 最近记录: |