Первый генератор паролей на Python
Это мой первый проект с использованием Python. Я сделал простой генератор паролей, который проверяет вводимые пользователем данные. Как я могу это улучшить?
import random
def password_generator():
password = []
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"]
password_length = 0
password_numbers = []
password_letters = []
# Input the length of the password
while True:
password_length_input = input("Choose the length of your password with numbers between 6 and 15:\n")
if not password_length_input.isnumeric():
print(f"{password_length_input} is not a number, try again:")
continue
else:
password_length = int(password_length_input)
print(f"Password length: {password_length}")
if 6 <= password_length <= 15:
break
else:
print("The password must be between 6 and 15 characters, try again:")
continue
# Input the amount of numbers in password
while True:
password_numbers_input = \
input(f"Choose the amount of numbers you want in your password, max {password_length}\n")
if not password_numbers_input.isnumeric():
print(f"{password_numbers_input} is not a number try again")
continue
elif int(password_numbers_input) > password_length:
password_numbers = 0
print(f"The value is too high, choose maximum {password_length} numbers")
continue
else:
password_numbers = int(password_numbers_input)
print(f"Password numbers: {password_numbers}")
for number in range(0,password_numbers):
password.append(random.randrange(0,9))
break
# Check for numbers and letters in password
while True:
if password_numbers == password_length:
print(f"The password will be only {password_numbers} numbers, no letters.")
break
else:
password_letters = password_length - password_numbers
print(f"""Your password will be {password_length} characters with {password_numbers} numbers and {password_letters} letters.""")
for letter in range(0,password_letters):
password.append(random.choice(letters))
break
random.shuffle(password)
password_string = ''.join([str(item) for item in password])
print(f"Your password is:\n{password_string}")
password_generator()
Пример использования:
Choose the length of your password with numbers between 6 and 15:
Password length: 8
Choose the amount of numbers you want in your password, max 8
Password numbers: 2
Your password will be 8 characters with 2 numbers and 6 letters.
Your password is:
pzc11bmf
Ответы
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"]
Этот метод написания алфавита очень подвержен ошибкам. Я бы импортировал stringи использовал string.ascii_lowercaseвместо letters. Если по какой-то причине вы хотите сгенерировать свой собственный диапазон букв, я бы написал
letters = [chr(n) for n in range(ord('a'), ord('z') + 1)]
так как тогда нет опасности пропустить или дублировать букву.
password_length = 0 password_numbers = [] password_letters = []
Эти значения по умолчанию никогда не используются. Значения по умолчанию password_numbersи password_lettersне имеют смысла, поскольку эти переменные содержат числа. Я бы удалил все три строки.
if not password_length_input.isnumeric(): print(f"{password_length_input} is not a number, try again:") continue else: password_length = int(password_length_input) print(f"Password length: {password_length}")
Я бы вместо этого написал
try:
password_length = int(password_length_input)
except ValueError:
print(f"{password_length_input} is not a number, try again:")
continue
print(f"Password length: {password_length}")
while True: if password_numbers == password_length: ... break else: ... break
Здесь нет смысла создавать whileцикл, так как вы всегда выходите из него на первой итерации.
range(0,password_numbers)
Вы можете просто написать range(password_numbers).
password.append(random.randrange(0,9))
Это добавит цифру от 0 до 8 включительно, никогда не 9. Если вам нужны все десять цифр, вы должны написать random.randrange(10). А может лучше использовать random.choice(string.digits).
password_string = ''.join([str(item) for item in password])
Если вы используете, string.digitsто каждый элемент passwordбудет символом, так что вы можете упростить это до password_string = ''.join(password).
Более простой способ создания случайной строки:
import random
import string
def get_random_string(length):
letters = string.ascii_lowercase
result_str = ''.join(random.choice(letters) for i in range(length))
print("Random string of length", length, "is:", result_str)
get_random_string(8)
get_random_string(8)
get_random_string(6)
заимствовано отсюда , и есть еще примеры.
Теперь, если у вас есть особые требования, такие как минимальное количество цифр, вы можете либо настроить формулу, либо сгенерировать два списка и объединить их, перетасовывая значения.
В приведенной выше ссылке есть пример: «Создать случайную буквенно-цифровую строку с фиксированным количеством букв и цифр» => объединение двух составных частей списка.
То, как вы это делаете, является процедурным, но не Pythonic. Это своего рода изобретение колеса.
По крайней мере, ваш список разрешенных символов должен выглядеть так:
letters = "abcdefghijklmnopqrstuvwxyz"
Затем вы выбираете случайную букву, например letters[3], вернет 'd', поскольку список основан на 0, а Python обрабатывает строки как последовательности символов. Используя перемешивание, как вы уже делаете, вы можете написать более лаконичный код.
Первый
Я предлагаю создать отдельные методы для каждого цикла while.
Второй
Я думаю, что цикл while True - не лучшая практика. Вместо этого используйте условие.
В третьих
Предлагаю создать класс PasswordGenerator, который будет содержать ваш код. Это поможет вам расширить ваш код в будущем.
Базовая структура для вашего проекта
class PasswordGenerator():
check_declared_password_length():
...
check_amount_of_password_numbers():
...
*
*
*
В конце концов, не забудьте создать функции с одной ответственностью. После этого вы можете писать модульные тесты для каждого из них, и это будет проще.