Python. Не могу разобраться как повторно вызвать функцию, если она не удовлетворяет условию
Друзья, не могу разобраться как повторно вызывать функцию до момента как она удовлетворит условию. Есть 2 функции - одна генерирует пароль, другая проверяет его на надежность. Как сделать так, чтобы функция генерировала новый пароль, пока он не станет надежным, а попытки генерации до надежного пароля выводила пользователю? Пробовал с циклом while, он у меня берет только один сгенерированный пароль и бесконечно его выводит будь он надежным или нет...
from random import randint
def generate():
MAX_NUMBER = 10
MIN_NUMBER = 7
Generate = chr(randint(33,126))
Password = []
Randomno = randint(MIN_NUMBER, MAX_NUMBER)
for i in range(Randomno):
Generate = chr(randint(33,126))
Password.append(Generate)
W = ''.join(Password)
return W
def nadezhnost(password):
has_upper = False
has_lower = False
has_numb = False
for ch in password:
if ch >= 'A' and ch <= 'Z':
has_upper = True
elif ch >= 'a' and ch <= 'z':
has_lower = True
elif ch >= '1' and ch <= '9':
has_numb = True
if len(password) >= 8 and has_upper and has_lower and has_numb:
return 'Генерируемый пароль является надежным'
else:
return 'Генерируемый пароль является ненадежным'
def main():
if __name__ == '__main__':
main()
Ответы (2 шт):
Как-то так.
from random import randint
def generate():
MAX_NUMBER = 10
MIN_NUMBER = 7
Generate = chr(randint(33,126))
Password = []
Randomno = randint(MIN_NUMBER, MAX_NUMBER)
for i in range(Randomno):
Generate = chr(randint(33,126))
Password.append(Generate)
W = ''.join(Password)
return W
def nadezhnost(password):
has_upper = False
has_lower = False
has_numb = False
for ch in password:
if ch >= 'A' and ch <= 'Z':
has_upper = True
elif ch >= 'a' and ch <= 'z':
has_lower = True
elif ch >= '1' and ch <= '9':
has_numb = True
return len(password) >= 8 and has_upper and has_lower and has_numb
while True:
password = generate()
if nadezhnost(password):
print('Надёжный пароль:', password)
break
else:
print('Ненадёжный пароль:', password)
В последней строчке проверки на надёжность поменял формат: функция возвращает True или False в зависимости от выполнения вашего условия.
UPD:
Счетчик можно вставить в цикл (перед циклом создаем переменную):
counter = 0
while True:
password = generate()
if nadezhnost(password):
print('Надёжный пароль:', password)
break
else:
print('Ненадёжный пароль:', password)
counter += 1
print(f'Ненадежный пароль был сгенерирован {counter} раз(а).')
Вариант который сразу позволяет учесть требования к безопасности пароля и настроить
from random import randint, shuffle, choices
from string import ascii_lowercase, ascii_uppercase, digits, punctuation
def generate(
# Заданная длина пароля (8 по умолчанию)
length: int = 8,
# Минимальное количество цифр в пароле (1 по умолчанию)
digits_min: int = 1,
# Минимальное количество букв в нижнем регистре в пароле (1 по умолчанию)
lower_case_letter_min: int = 1,
# Минимальное количество букв в верхнем регистре в пароле (1 по умолчанию)
upper_case_letter_min: int = 1,
# Минимальное количество специальных символов (знаков пунктуации или других заданных) в пароле (0 по умолчанию)
special_characters_min: int = 0,
# Набор специальных символов используемых при создании пароля
special_characters: str = punctuation
):
# Создаем шаблон карты символов пароля,
# то есть сколько каких символов должно быть в пароле
password_map = [0, 0, 0, 0]
# заполняем карту рандомными значениями от минимального количества символов до длины пароля до тех пор,
# пока сумма всех элементов карты не будет равна заявленной длине пароля
while sum(password_map) != length:
password_map = [
# конструкция `and` в данном случае позволяет гарантированно использовать 0
# если параметр определяющий минимальное количество символов равен нулю и рандомное значение
# от минимально до длины пароля в противном случае
digits_min and randint(digits_min, length),
lower_case_letter_min and randint(lower_case_letter_min, length),
upper_case_letter_min and randint(upper_case_letter_min, length),
special_characters_min and randint(special_characters_min, length)
]
# Распаковываем в переменные карту пароля
digits_len, lower_case_letters_len, upper_case_letters_len, special_characters_len = password_map
# Собираем пароль по карте (описание choices см. в документации к библиотеке random)
password_char_list = (
choices(digits, k=digits_len) +
choices(ascii_lowercase, k=lower_case_letters_len) +
choices(ascii_uppercase, k=upper_case_letters_len) +
choices(special_characters, k=special_characters_len)
)
# Перемешиваем список символов
shuffle(password_char_list)
# объединяем список в строку и возвращаем в виде результата
return ''.join(password_char_list)
if __name__ == '__main__':
print(
generate(),
generate(length=20),
generate(length=15, special_characters='$#@', special_characters_min=2),
generate(length=10, special_characters_min=1),
sep='\n'
)
# C6e8LwF2
# VYVrQLrEZ50hlj2Zq91S
# 2@3415N42$#@h00
# w7Y64YM`73
А задуманную Вами проверку я бы сделал так
def is_safe(
password,
/,
password_min_length: int = 8,
digits_min: int = 1,
lower_case_letter_min: int = 1,
upper_case_letter_min: int = 1
):
return all(
[
len(password) >= password_min_length,
len([*filter(lambda x: x in digits, password)]) >= digits_min,
len([*filter(lambda x: x in ascii_lowercase, password)]) >= lower_case_letter_min,
len([*filter(lambda x: x in ascii_uppercase, password)]) >= upper_case_letter_min
]
)