Python 在iterable上循环时停止检查条件
所以我有一个问题。假设我们正在进行标准密码强度检查,这意味着如果密码字符串中包含大写字母、小写字母和数字,则认为它是强密码 我想到的超级简单的例子:Python 在iterable上循环时停止检查条件,python,loops,for-loop,if-statement,Python,Loops,For Loop,If Statement,所以我有一个问题。假设我们正在进行标准密码强度检查,这意味着如果密码字符串中包含大写字母、小写字母和数字,则认为它是强密码 我想到的超级简单的例子: for character in 'asdASD123': if character.isupper(): something if character.islower(): something if character.isnumeric(): something 如果在任何时候都满足所有这些条件,那么密码就
for character in 'asdASD123':
if character.isupper():
something
if character.islower():
something
if character.isnumeric():
something
如果在任何时候都满足所有这些条件,那么密码就是强密码。我的问题是:如果某个条件已经满足,是否有可能停止检查?在本例中,将在第一个字符上满足孤岛条件。有没有办法避免在进一步的循环中检查它?如果是,如何做到这一点?有没有一种方法可以将条件存储在列表中,然后在满足条件后将其从列表中删除,或者类似的方法?有几种解决方案。你可以做以下事情
super_cond = False
lower_cond = False
numeric_cond = False
for character in 'asdASD123':
if not super_cond and character.isupper():
super_cond = True
#something
if not lower_cond and character.islower():
lower_cond = True
#something
if not numeric_cond and character.isnumeric():
numeric_cond = True
#something
如果你想使用列表,你可以这样做
conditions = [False,False,False]
for character in 'asdASD123':
if not conditions[0] and character.isupper():
conditions[0] = True
#something
if not conditions[1] and character.islower():
conditions[1] = True
#something
if not conditions[2] and character.isnumeric():
conditions[2] = True
#something
是的,有很多方法可以做到这一点
这里有一个例子
可以使用真/假值创建字典。
像这样:
您可以尝试多种方法,其中一种方法如下:
is_lower, is_upper, is_numeric = False, False, False
for character in 'asdASD123':
if is_lower and is_upper and is_numeric:
return "Strong password" #print("Strong Password")
if character.isupper() and not is_upper:
is_upper = True
something
if character.islower() and not is_lower:
is_lower = True
something
if character.isnumeric() and not is_numeric:
is_numeric = True
something
对于这种情况,我建议使用正则表达式来避免循环
import re
password= 'asdASD1'
pattern = re.compile(r"^(?=.*[\d])(?=.*[A-Z])(?=.*[a-z])")
if re.match(pattern, password): #if it meets condition
# do somethin
您可以利用|逻辑“or”短路的事实,在满足条件后消除检查
通过短路,我的意思是,如果有一个表达式:x | y,那么只有当x为False时才计算y
这也允许一些简洁。例如
contains_upper = False
contains_lower = False
contains_numeric = False
for char in "asdASD123":
contains_upper |= char.isupper()
contains_lower |= char.islower()
contains_numeric |= char.isnumeric()
strong = contains_upper and contains_lower and contains_numeric
我觉得这段代码是非常地道的Python代码,可读性很强。您可以这样做,通过引入标志布尔指示符来跟踪哪些检查已经通过:
upper_flag = False
lower_flag = False
numeric_flag = False
for character in 'asdASD123':
if character.isupper() and not upper_flag:
something
upper_flag = True
if character.islower() and not lower_flag:
something
lower_flag = True
if character.isnumeric() and not numeric_flag:
something
numeric_flag = True
这就是说,如果目标是节省时间,则密码必须非常长才能节省大量时间,或者您必须检查很多密码
另一方面,这些标志还有其他用途,比如存储或显示给定密码通过的检查次数。下面给出了一个快速而肮脏的示例,但与打印相比,您更希望以某种方式存储此信息
def password_checker(password):
upper_flag = False
lower_flag = False
numeric_flag = False
for character in password:
if character.isupper() and not upper_flag:
upper_flag = True
if character.islower() and not lower_flag:
lower_flag = True
if character.isnumeric() and not numeric_flag:
numeric_flag = True
flag_list = [upper_flag, lower_flag, numeric_flag]
print(f"Password: '{password}' passes {sum(flag_list)}/{len(flag_list)} checks:\n")
print(" - Contains upper case character:\t", upper_flag )
print(" - Contains lower case character:\t", lower_flag )
print(" - Contains numeric character: \t", numeric_flag )
password_checker('asdASD123')
返回:
Password: 'asdASD123' passes 3/3 checks:
- Contains upper case character: True
- Contains lower case character: True
- Contains numeric character: True
Regex可能是最好的解决方案,但这里有一个解决方案,其中循环位于不同的位置。这可以修改为不每次都执行相同的循环 我已经包装了每个函数,以便您可以看到实际调用了什么
def print_and(fun_name):
def wrapper(c):
fun = getattr(c, fun_name)
result = fun()
print(f"'{c}'.{fun_name} == {result}")
return result
return wrapper
is_lower = print_and("islower")
is_upper = print_and("isupper")
is_digit = print_and("isdigit")
def check_characters(characters):
return (
any(is_lower(c) for c in characters)
and any(is_upper(c) for c in characters)
and any(is_digit(c) for c in characters)
)
print(bool(check_characters("asdASD123")))
print(bool(check_characters("123")))
获取此结果:
'a'.islower == True
'a'.isupper == False
's'.isupper == False
'd'.isupper == False
'A'.isupper == True
'a'.isdigit == False
's'.isdigit == False
'd'.isdigit == False
'A'.isdigit == False
'S'.isdigit == False
'D'.isdigit == False
'1'.isdigit == True
True
'1'.islower == False
'2'.islower == False
'3'.islower == False
False
您可以看到,每个函数只有在前一个函数返回true时才会被调用。对此的改进是只检查上一个函数退出点的字符串的其余部分。尝试:
passwd = "sdnkdj98KJ/"
def passcheck(passwd):
upper = any(map(lambda x:x.isupper(),passwd))
num = any(map(lambda x:x.isnumeric(),passwd))
lower = any(map(lambda x:x.islower(),passwd))
return "strong passwd" if upper and lower and num else "weak passwd"
根据评论,我为提供的两个解决方案添加了100000次复制的性能差异基准。为了公平地对待另一个解决方案的作者,我还将我的解决方案封装在一个函数声明块中,因为这些块也会占用CPU时间
我的答覆是:
from datetime import datetime
start = datetime.now()
for i in range(100000):
a = passcheck(passwd)
print(datetime.now()-start) # output: 0:00:00.205365, so 205.4ms
达芬奇1913年的回答:
start = datetime.now()
for i in range(100000):
password_checker(passwd)
print(datetime.now()-start) # output: 0:00:00.225257, so 225ms
所以我的答案恰好快了一点,但我不会太注意20毫秒的差异。大多数情况下,我的回答更简洁,更具可读性。这两种方法都能很好地执行。您可以做的是做相反的事情,比如检查是否没有小写字母或没有特殊字符,最后只需设置密码。此外,也没有必要为loop@Cbhihe如果第一个字符是唯一的数字字符,会发生什么情况?@Cbhihe我明白了。那么,您提出了一个具有多个for循环的解决方案?仍然不确定“缩进每个连续条件”是什么意思……这是pythonic,但不能解决问题,因为每个函数都是针对每个字符执行的。目标是仅在前一个成功的情况下执行后续函数。@bluetooth我的观点是,由于|是短路,因此一旦相应的条件为真,函数实际上就不会执行。不是这样吗?啊,是的。很好,我没有意识到。我不知道这个成语。你教了我一些东西:加1。+1:漂亮简洁的Ade_1,但看看我的解决方案。我只使用基本方法,不使用正则表达式,同时也避免使用for循环。这实际上是我在检查这个解决方案的答案之前设法想出的一个字符对一个字符的方法;选中另一个解决方案,因为它引入了一种新方法。不知道哪一个表现更好though@entman:添加了基准测试,以便您可以看到哪个答案更快。
start = datetime.now()
for i in range(100000):
password_checker(passwd)
print(datetime.now()-start) # output: 0:00:00.225257, so 225ms