2

I am creating a password generator the takes the length of the desired password, number of letters, as well as the number of numbers. The password needs to contain uppercase letters as well as numbers and special characters. I am having trouble figuring out how to specify the number of letters and numbers in the password. This is what I have so far:

import random

charslet ="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
charsnum = "1234567890"
charssym = "!@#$%^&*"

def password():
    pwd = ""

    passlen = int(input("How long do you want the password to be?: "))
    passlet = int(input("How many letters do you want in your password?: "))
    passnum = int(input("How many numbers do you want in your password?: "))
    passsym = int(passlen - (passlet + passnum))
    chars = ""

    for let in range(passlet):
        chars += random.choice(charslet)
    for num in range(passnum):
        chars += random.choice(charsnum)
    for sym in range(passsym):
        chars += random.choice(charssym)



    for p in range(passlen):
        pwd += random.choice(chars)

    print(pwd)

password()

3
  • For starters, do not give your function and a local variable the same name. And it looks like you did specify both numbers. Please clarify your question. Commented Sep 29, 2020 at 23:25
  • Thank you, I just changed it to pwd. And when I run the program and input my variables, the outputted password doesn't follow the criteria I had. for example I put 10 for passlen , 3 for passlet , and 3 for passnum. So in theory I should receive a password with 3 letters, 3 numbers, and 4 symbols but I received 4##&$*c40# as my output. Commented Sep 29, 2020 at 23:33
  • 1
    There is a Python idiom you can use here: when you are doing a for loop and you don't care about the values from the range() you can use a single underscore as your variable name: _ Your code uses let, num, and sym as the variable names for the loop values, but your code doesn't ever need to use them for anything. This isn't wrong, but using the _ idiom is almost like putting in a comment saying "we don't care about the loop value here, we just want to loop a specific number of times". Commented Sep 30, 2020 at 0:16

2 Answers 2

3

I think the last part is what is confusing you. You are building the chars variable with the correct amount of specific chars, but you then choose between them again at the end.

You could just change:

for p in range(passlen):
    password += random.choice(chars)

With

# option 1 - works better if working with lists
list_chars = list(chars)
random.shuffle(chars)
password = "".join(list_chars)

# option 2 - simpler solution for strings
password = "".join(random.sample(char, len(char)))

You could also use shuffle to select the chars before without the for loops, something like:

# for this to work your `charslet` must be a list
random.shuffle(charslet)
chars += "".join(charslet[:passlet])
Sign up to request clarification or add additional context in comments.

4 Comments

I followed your first suggestion but in turn get TypeError: 'str' object doesn't not support item assignment
I've fixed the code, shuffle doesn't work with strings, you have to use lists, so in this case, I converted the current string into a list and joined it back into a string after shuffling. It should now work.
included a new option using random.sample
Thank you very much, I changed the strings being shuffled to a list as you said and it works just fine.
1

This is the corrected code:

    import random

    charslet ="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
    charsnum = "1234567890"
    charssym = "!@#$%^&*"

    def password():
        pwd = ""

        passlen = int(input("How long do you want the password to be?: "))
        passlet = int(input("How many letters do you want in your password?: "))
        passnum = int(input("How many numbers do you want in your password?: "))
        passsym = int(passlen - (passlet + passnum))
        chars = ""

        for let in range(passlet):
            chars += random.choice(charslet)
        for num in range(passnum):
            chars += random.choice(charsnum)
        for sym in range(passsym):
            chars += random.choice(charssym)



        list_chars = list(chars)
        random.shuffle(list_chars)
        pwd = "".join(list_chars)

        print(pwd)

    password()

I replaced:

    for p in range(passlen):
        password += random.choice(chars)

with

    list_chars = list(chars)
    random.shuffle(list_chars)
    pwd = "".join(list_chars)

Putting the altered chars variable in a list allowed me to shuffle it, randomizing it and allowing me to assign it to pwd

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.