greenlantern02
greenlantern02

Reputation: 29

Is there a way to reduce the number of ifs?

I am learning the basics of Python and am writing a password generator. It is supposed to ask the user what type of password they want and the desired length. Is there a way to shorten the code below? I think I am using a lot of ifs. Any feedback is greatly appreciated.

`import random
import string

ans_n = input('Do you want numbers in your password?(y/n) ')
ans_l = input('Do you want letters in your password?(y/n) ')
ans_s = input('Do you want special characters in your password?(y/n) ')


def random_numbers(user_numbers_length):
    digits = []
    for i in range(user_numbers_length):
        digits.append(str(random.randint(1, 10)))

    return digits


def random_letters(user_letter_length):
    return random.sample(string.ascii_letters, user_letter_length)


def random_characters(user_special_length):
    stringSpecial = []
    for i in range(user_special_length):
        stringSpecial.append(random.choice('!$%&()*+,-.:;<=>?@[]^_`{|}~'))

    return stringSpecial

if ans_l == 'y' and ans_n == 'n' and ans_s == 'n':
    print("how many letters do you want in your password?")
    user_letter_length = input()
    password = random_letters(int(user_letter_length))

if ans_l == 'y' and ans_n == 'y' and ans_s == 'n':
    print("how many letters do you want in your password?")
    user_letter_length = input()
    print("how many numbers do you want in your password?")
    user_numbers_length = input()
    password = random_letters(int(user_letter_length)) + random_numbers(int(user_numbers_length))

if ans_l == 'y' and ans_n == 'y' and ans_s == 'y':
    print("how many letters do you want in your password?")
    user_letter_length = input()
    print("how many numbers do you want in your password?")
    user_numbers_length = input()
    print("how many special characters do you want in your password?")
    user_special_length = input()
    password = random_letters(int(user_letter_length)) + random_numbers(int(user_numbers_length)) + random_characters(
        int(user_special_length))

if ans_l == 'n' and ans_n == 'y' and ans_s == 'n':
    print("how many numbers do you want in your password?")
    user_numbers_length = input()
    password = random_numbers(int(user_numbers_length))

if ans_l == 'n' and ans_n == 'y' and ans_s == 'y':
    print("how many numbers do you want in your password?")
    user_numbers_length = input()
    print("how many special characters do you want in your password?")
    user_special_length = input()
    password = random_numbers(int(user_numbers_length)) +random_characters(int(user_special_length))

if ans_l == 'n' and ans_n == 'n' and ans_s == 'y':
    print("how many special characters do you want in your password?")
    user_special_length = input()
    password = random_characters(int(user_special_length))

if ans_l == 'y' and ans_n == 'n' and ans_s == 'y':
    print("how many letters do you want in your password?")
    user_letter_length = input()
    print("how many special characters do you want in your password?")
    user_special_length = input()
    password = random_letters(int(user_letter_length)) +random_characters(int(user_special_length))

random.shuffle(password)

print(f"Your generated password is: ")
print(''.join(password))
`

Upvotes: 1

Views: 411

Answers (3)

Cohan
Cohan

Reputation: 4544

Rather than a lot of asking questions, if you know you're going to have to ask for each character class, you can just ask the numbers upfront. You can suggest they enter 0 if they don't want any. Then it's a matter of calling random.choices() with the number specified in k=#. Finally, you shuffle the password at the end of the process.

This approach also minimizes the number of questions the user has to answer. If the user wants letters, they can just tell you how many they want rather than having to tell you yes, and then tell you how many.

import random
import string

ans_l = int(input("How many letters do you want (0 for none)? "))
ans_n = int(input("How many numbers do you want (0 for none)? "))
ans_s = int(input("How many specials do you want (0 for none)? "))

password = []
password += random.choices(string.ascii_letters, k=ans_l)
password += random.choices(string.digits, k=ans_n)
password += random.choices(string.punctuation, k=ans_s)

random.shuffle(password)
print(''.join(password))

A sample interaction would look like...

~$ python3 generate_password.py 
How many letters do you want (0 for none)? 4
How many numbers do you want (0 for none)? 4
How many specials do you want (0 for none)? 4
5N+46d9I_\"Z

Or without special characters

~$ python3 so.py 
How many letters do you want (0 for none)? 6
How many numbers do you want (0 for none)? 6
How many specials do you want (0 for none)? 0
9N0Y5X0p29yG

Upvotes: 3

blhsing
blhsing

Reputation: 106553

Since your random_numbers, random_letters and random_characters functions differ only in the character sets they use, you can use a dict to map the display names to the character sets, and then iterate through the dict items to ask for inputs instead:

import random
import string

character_sets = {
    'numbers': string.digits,
    'letters': string.ascii_letters,
    'special characters': string.punctuation
}

characters = []
for name, value in character_sets.items():
    if input(f'Do you want {name} in your password?(y/n) ') == 'y':
        characters.extend(random.choices(value, k=int(input(f'How many {name} do you want in your password? '))))
random.shuffle(characters)
print(f'Your generated password is : {"".join(characters)}')

Upvotes: 3

enzo
enzo

Reputation: 11496

Just to something like:

user_letter_length = None
user_numbers_length = None
user_special_length = None

if ans_l == 'y':
    print("how many letters do you want in your password?")
    user_letter_length = input()

if ans_n == 'y':
    print("how many numbers do you want in your password?")
    user_numbers_length = input()

if ans_s == 'y':
    print("how many special characters do you want in your password?")
    user_special_length = input()

Then when you create the password, just check if any of user_letter_length, user_numbers_length or user_special_length is None. If any variable is None, it's because the user did not set them.

Upvotes: 2

Related Questions