当我通过测试以下代码时
PWD = create_password(4, 5, 8, 10, 72, True)
show_created_password(PWD)
没有打印任何值。一开始我使用yield
,但问题发生后,我尝试了return
,但问题仍然存在。如何解决此问题?
原始代码:
"""
Generator Module for Password Manager
"""
# Imports
from passwordmeter import test
from random import choice, randint
import string_utils
# Generator
words = open('words.txt', 'r').read().split('n')
special_chars = ['!', '?', '%', '$', '*', '(', ')', '&', '@', '#', '^', '+', '=', '-', '_', '"', ';', ':', '<', '>', '/', '\']
uppercase_letters = ['A','B','C','D','E','F','G','H','I','J','K','L''M','N', 'O', 'P','Q','R','S','T','U','V','W','X','Y','Z']
def create_password(num_words, num_numbers, num_special, num_uppercase_words, char_limit = 0, Strengthen = False):
"""
Generates Pasword from words, Uppercase letters, special chars, and numbers with the options of:
:param num_words: Number of Words in password.
:param num_numbers: Number of numbers in password.
:param num_special: Number of Special Characters in password.
:param num_uppercase_words: Number of uppercase words in password.
:param char_limit: Limit of characters in password.
:param Strengthen: Strengthens the password.
"""
#TODO Connect the arguments with wx for user customization.
pass_str = ' '
if char_limit > 0:
while True:
if len(pass_str) == char_limit:
if Strengthen == True:
pass_str = string_utils.shuffle(pass_str)
pass_str = pass_str.replace(" ", "")
yield pass_str
else:
yield pass_str
break
else:
for _ in range(num_words):
pass_str+=choice(words).lower().capitalize()
for _ in range(num_numbers):
pass_str==str(randint(0,100))
for _ in range(num_special):
pass_str+=choice(special_chars)
for _ in range(num_uppercase_words):
pass_str+=choice(uppercase_letters)
else:
for _ in range(num_words):
pass_str+=choice(words).lower().capitalize()
for _ in range(num_numbers):
pass_str+=str(randint(0,100))
for _ in range(num_special):
pass_str+=choice(special_chars)
for _ in range(num_uppercase_words):
pass_str+=choice(uppercase_letters)
if Strengthen == True:
pass_str = string_utils.shuffle(pass_str)
pass_str = pass_str.replace(" ", "")
yield pass_str
else:
yield pass_str
def show_created_password(created_password):
"""
Shows password generated by generator
"""
for value in created_password:
pass_str = value
strength,_=test(pass_str)
#TODO make print statements into wx form in the mainapp.py file or through a different wx method
print('nPassword: %s'%pass_str)
print('Strength: %0.5f'%strength)
首先,忘记yield
,使用return
。yield
用于生成一种特殊类型的函数,该函数可以运行多次,并在几个步骤中给出输出。例如,我可以用yield
实现一个primes
函数,这样每次调用它时,它都会给我下一个素数:
def primes():
for n in (1, 2, 3, 5, 7, 11, 13, 17, 19): # Instead of this you would actually compute the numbers
yield n
prime_numbers = primes()
next(prime_numbers) # 1
next(prime_numbers) # 2
next(prime_numbers) # 3
next(prime_numbers) # 5
next(prime_numbers) # 7
问题是while True
循环永远不会结束。结束该循环的唯一方法是使用break
,并且只有当过程的长度和字符限制完全相等时才会执行该代码,这很可能不会发生,因为每次迭代都要添加大量字符。假设您每次迭代添加50个字符,并且您的限制是75。第一次迭代条件为False(长度为0,限制为75(,因此我们添加了50个字符。第二次迭代条件为False(长度50,限制75(,因此我们再添加50个字符。第三次迭代为False(长度为100,限制为75(,因此我们再添加50个字符。您将永远迭代,并且限制永远不会与长度相同,长度将不断增长,直到您耗尽内存。
show_password
也有一个错误。当您传递创建的密码时,您传递的是一个字符串。所以你需要去掉循环。我想你有这个循环是因为你错误地使用了yield
。
def create_password(num_words, num_numbers, num_special, num_uppercase_words, char_limit = 0, strengthen = False):
"""
Generates password from words, uppercase letters, special chars, and numbers with the following options:
:param num_words: number of words in password
:param num_numbers: number of numbers in password
:param num_special: number of special characters in password
:param num_uppercase_words: number of uppercase words in password
:param char_limit: limit of characters in password
:param strengthen: strengthens the password
"""
# TODO: Connect the arguments with wx for user customization.
pass_str = ''.join(
[choice(words).lower().capitalize() for _ in range(num_words)] +
[str(randint(0,100)) for _ in range(num_numbers)] +
[choice(special_chars) for _ in range(num_special)] +
[choice(uppercase_letters) for _ in range(num_uppercase_words)]
)
if strengthen:
pass_str = string_utils.shuffle(pass_str)
pass_str = pass_str.replace(' ', '')
if char_limit > 0:
pass_str = pass_str[:char_limit]
return pass_str
def show_created_password(pass_str):
"""
Shows password generated by generator
"""
strength, _ = test(pass_str)
#TODO make print statements into wx form in the mainapp.py file or through a different wx method
print("Password: {:s}".format(pass_str))
print("Strength: {:0.5f}".format(strength))
print()
首先,如果是字符限制,则不需要任何循环,如果长度最小,则需要一个循环,但字符限制只需要确保在长度过长的情况下在末尾进行剪切。
Strengthen
不应该用作变量、参数或函数名,标题大小写名称是为类名保留的,我将其更改为stregthen
。我将添加到密码中的所有循环更改为[SOMETHING for _ in range(SOMENUMBER)]
形式的列表理解。这将创建一个包含该数量元素的列表。然后,我添加了所有列表,将它们合并到一个列表中,然后用空字符串""
将其连接起来。基本上,这会将列表中的所有项目连接到一个字符串中。一旦我们有了绳子,我们会检查是否需要加强它,然后我们会检查我们是否超过了极限来减少它。之后,我们可以返回密码。
另一种方法基本相同,删除了循环,但我使用了"Hello {}".format("world!")
方式,我建议您使用它来代替"Hello %s"%"world!"
。