我的代码通过了验证,但运行速度很慢
My code passes validation, but runs very slowly
def is_password_good(password):
if len(txt) > 7 and [i for i in txt if i.isupper()] and [i for i in txt if i.islower() and [i for i in txt if i.isnumeric()]]:
return True
else:
return False
txt = input()
print(is_password_good(txt))
您可以迭代每个 method
作为您的条件,并在满足条件时中断以节省资源。
def is_password_good(password):
if len(password) > 7:
password = set(password)
for method in (str.isupper,
str.islower,
str.isnumeric):
for i in password:
if method(i):
break
else:
return False
return True
else:
return False
>>> is_password_good('1234567')
False
>>> is_password_good('12345678')
False
>>> is_password_good('123456aa')
False
>>> is_password_good('123456aB')
True
这个方法:
- 条件满足时中断
- 为了避免浪费计算时间检查已证明正确的答案
- space 的复杂度为
O(<=n)
- 转换为
set
删除了重复的字母
- 可扩展以实现更多功能
- 只需将另一个
lambda
函数添加到 method
元组
你正在 运行 三个 for
循环,一个接一个,而你可以 运行 一个 for
循环:
def is_password_good(password, good_length):
if len(password) < good_length:
return False
has_upper, has_lower, has_digit = False, False, False
for char in set(password):
has_upper = char.isupper() or has_upper
has_lower = char.islower() or has_lower
has_digit = char.isdigit() or has_digit
if has_upper and has_lower and has_digit:
return True
return False
想象一个所有小写字母的密码——您必须检查每个字母以查看您是否也得到了数字或大写字母,因此您将遍历所有 n
unique 个字符,才能确定密码不满足要求。这意味着在 worst-case 场景中,您可能做的最好的事情是 O(n)
(同样,其中 n
是 unique 字符的数量字符串)。
然后的想法应该是尽快跳出循环——在这种情况下,一旦所有三个标志都切换到True
。
三个 char.isxxx() or has_xxx
语句中的每一个在第一次满足检查时将永远 True
,因为在第一次之后它是 True
,语句减少到 char.isxxx() or True
这将永远是真的。
三个标志都设置好后,可以break然后return是否也满足good_length
如果您正在寻找大写字母,使用您正在使用的方法,每个字母都将被评估。因此,如果您的字符串中有 50 个字母,并且您正在使用列表推导式方法,那么您将为每个列表做 50 件事。在您的情况下,有三个列表推导式,因此每次都会进行 len(txt) * 3
次评估。
使用您的方法,修改内联密码以使 timeit 调用更简单:
import timeit
def is_password_good():
txt = "Sup3rlongpassword"
if (
len(txt) > 7
and [i for i in txt if i.isupper()]
and [i for i in txt if i.islower() and [i for i in txt if i.isnumeric()]]
):
return True
else:
return False
>>> timeit.timeit(is_password_good)
17.099690434522927
这是一个使用正则表达式的方法。在每种情况下,一旦满足通过条件,它就会 return 值。
import re
has_upper = re.compile('[A-Z]').search
has_lower = re.compile('[a-z]').search
has_digit = re.compile('[0-9]').search
def is_password_good_re():
txt = "Sup3rlongpassword"
if len(txt) > 7 and has_upper(txt) and has_lower(txt) and has_digit(txt):
return True
else:
return False
>>> timeit.timeit(is_password_good_re)
0.8171015260741115
编辑:
还有一点很突出,您的一个列表嵌套在另一个列表中。
[i for i in txt if i.islower() and [i for i in txt if i.isnumeric()]]
所以这意味着每个字符都会进行数字检查。那么如果密码有10个字符,那么对数字进行10次检查,每次检查10次,总共对数字进行100次评估。
def is_password_good(password):
if len(txt) > 7 and [i for i in txt if i.isupper()] and [i for i in txt if i.islower() and [i for i in txt if i.isnumeric()]]:
return True
else:
return False
txt = input()
print(is_password_good(txt))
您可以迭代每个 method
作为您的条件,并在满足条件时中断以节省资源。
def is_password_good(password):
if len(password) > 7:
password = set(password)
for method in (str.isupper,
str.islower,
str.isnumeric):
for i in password:
if method(i):
break
else:
return False
return True
else:
return False
>>> is_password_good('1234567')
False
>>> is_password_good('12345678')
False
>>> is_password_good('123456aa')
False
>>> is_password_good('123456aB')
True
这个方法:
- 条件满足时中断
- 为了避免浪费计算时间检查已证明正确的答案
- space 的复杂度为
O(<=n)
- 转换为
set
删除了重复的字母
- 转换为
- 可扩展以实现更多功能
- 只需将另一个
lambda
函数添加到method
元组
- 只需将另一个
你正在 运行 三个 for
循环,一个接一个,而你可以 运行 一个 for
循环:
def is_password_good(password, good_length):
if len(password) < good_length:
return False
has_upper, has_lower, has_digit = False, False, False
for char in set(password):
has_upper = char.isupper() or has_upper
has_lower = char.islower() or has_lower
has_digit = char.isdigit() or has_digit
if has_upper and has_lower and has_digit:
return True
return False
想象一个所有小写字母的密码——您必须检查每个字母以查看您是否也得到了数字或大写字母,因此您将遍历所有 n
unique 个字符,才能确定密码不满足要求。这意味着在 worst-case 场景中,您可能做的最好的事情是 O(n)
(同样,其中 n
是 unique 字符的数量字符串)。
然后的想法应该是尽快跳出循环——在这种情况下,一旦所有三个标志都切换到True
。
三个 char.isxxx() or has_xxx
语句中的每一个在第一次满足检查时将永远 True
,因为在第一次之后它是 True
,语句减少到 char.isxxx() or True
这将永远是真的。
三个标志都设置好后,可以break然后return是否也满足good_length
如果您正在寻找大写字母,使用您正在使用的方法,每个字母都将被评估。因此,如果您的字符串中有 50 个字母,并且您正在使用列表推导式方法,那么您将为每个列表做 50 件事。在您的情况下,有三个列表推导式,因此每次都会进行 len(txt) * 3
次评估。
使用您的方法,修改内联密码以使 timeit 调用更简单:
import timeit
def is_password_good():
txt = "Sup3rlongpassword"
if (
len(txt) > 7
and [i for i in txt if i.isupper()]
and [i for i in txt if i.islower() and [i for i in txt if i.isnumeric()]]
):
return True
else:
return False
>>> timeit.timeit(is_password_good)
17.099690434522927
这是一个使用正则表达式的方法。在每种情况下,一旦满足通过条件,它就会 return 值。
import re
has_upper = re.compile('[A-Z]').search
has_lower = re.compile('[a-z]').search
has_digit = re.compile('[0-9]').search
def is_password_good_re():
txt = "Sup3rlongpassword"
if len(txt) > 7 and has_upper(txt) and has_lower(txt) and has_digit(txt):
return True
else:
return False
>>> timeit.timeit(is_password_good_re)
0.8171015260741115
编辑:
还有一点很突出,您的一个列表嵌套在另一个列表中。
[i for i in txt if i.islower() and [i for i in txt if i.isnumeric()]]
所以这意味着每个字符都会进行数字检查。那么如果密码有10个字符,那么对数字进行10次检查,每次检查10次,总共对数字进行100次评估。