错误的随机密码生成器 (Python 3)

Faulty Random Password Generator (Python 3)

我开始学习 Python 并开始尝试使用示例代码块。我编辑了几次,在我最后一次编辑时,我添加了一个可选的随机密码生成器。然后我决定将密码生成器放在一个单独的文档中更有意义,所以我复制了必要的代码并制作了一个新文档。然而,在编辑它之后,我无法在密码中生成偶数位数字。

Pastebin

Copy of Faulty Code (Pastebin)

import math
import random
alpha = ['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']
print('Would you like a random password suggestion generator', 'Yes or No')
permissionRandomGenerator = input().lower()
print('How long do you want your password?')
lengthRandomGenerator = int(input())
if permissionRandomGenerator == 'yes':
    def randInt():
        return math.floor(random.random()*10)
    def randChar():
        return alpha[math.floor(random.random()*27)]
    randPasswordList = []
    listInsert = 0
    def changeCase(f):
        g = round(random.random())
        if g == 0:
            return f.lower()
        elif g == 1:
            return f.upper()
    while listInsert < lengthRandomGenerator:
        randPasswordList.insert(listInsert, randInt())
        listInsert = listInsert + 1
        if listInsert >= lengthRandomGenerator:
            break
        randPasswordList.insert(listInsert, randChar())
        randPasswordList[listInsert] = changeCase(randPasswordList[listInsert])
        listInsert = listInsert + 1
        continue
    listInsert = 0
    printList = 0
    if lengthRandomGenerator <= 0:
        print('It has to be longer than that')
    elif lengthRandomGenerator >= 25:
        print('I can\'t generate a password that long')
    elif math.isnan(lengthRandomGenerator):
        print('error: not valid data type')
    else:
        while printList < (len(randPasswordList)-1):
            printItem = randPasswordList[printList]
            print(printItem)
            printList = printList + 1
    printList = 0
    randPasswordList = []
elif permissionRandomGenerator == 'no':
    print('Too bad...')
else:
    print('You had to answer Yes or No')

我稍微重构了你的程序,去掉了很多不必要的步骤和不一致的地方。这里是完整的,然后我会解释每个部分:

import random
import string
import sys

possible_chars = string.ascii_letters + string.digits + string.punctuation

def nextchar(chars):
    return random.choice(chars)

yes_or_no = input("""
Would you like a random password suggestion generated?
Type Yes to continue: """).lower()

if yes_or_no == 'yes':
    try:
        pwd_len = int(input('How long do you want your password? '))
    except ValueError:
        sys.exit("You need to enter an integer. Please start the program over.")

    if 0 < pwd_len < 26:
        new_pwd = ""
        for _ in range(pwd_len):
            new_pwd += nextchar(possible_chars)
        print("Your new password is:\n" + new_pwd)

    else:
        print("I can only generate passwords between 1 and 25 characters long.")

else:
    print("Well then, why did you run me?")

Python 不仅仅是语法和 builtin functions, it is also the standard library 或 stdlib。您将一直使用 stdlib 的模块,所以当您认为您将使用一个模块时,阅读文档!您将了解该模块,它是什么预期用途是它的一些历史和变化(例如在哪个版本中添加了某个功能),以及其中包含的所有 类、功能和属性。确保你阅读了整篇文章(none 其中有 长)并尝试至少对每件事的作用有一个基本的了解。这样,例如在这种情况下,您就可以为工作选择最佳功能。我喜欢在空闲时间做的一件事就是随机选择一个模块并阅读文档,只是为了学习。它们通常写得相当好,而且通常非常包容。习惯 Monty Python 引用,它们无处不在。

import random
import string
import sys

进口排在第一位,而且应该几乎总是排在最前面。我喜欢按字母顺序排列我的,stdlib 在最上面,然后是一个空行,然后是 3rd 方模块,包括自己编写的模块。在导入之后也放一两行空行。要记住一件事,我在评论中提到过:可读性很重要。代码不仅要供机器阅读,还应供人阅读。必要时发表评论。慷慨地使用空格(还请记住,空格在 Python 中在句法上也很重要,因此它会迫使您正确缩进)以分隔相关的代码位、函数、类、块等。我 高度 推荐阅读、重读并花时间思考 PEP-8,Python 风格指南。它的建议不是 绝对 ,但许多强制执行编码标准的项目都依赖它。尽可能多地遵循它。如果一行有 83 个字符,请不要着急,但要注意自己在做什么。

我如此看重文档的原因是以下几行:

possible_chars = string.ascii_letters + string.digits + string.punctuation

def nextchar(chars):
    return random.choice(chars)

他们去掉了大约一半的代码。 string 包含一组用于处理字符串的预定义常量。我选择的三个应该都是好的有效密码字符。如果您使用的系统不带标点符号,只需将其删除即可。请注意,possible_chars 是一个字符串 - 与元组、列表和字典一样,字符串是可迭代的,因此您无需为每个可能的字符创建单独的列表。

接下来是函数 - 它替换了您的 randInt()randChar()changeCase() 函数,以及一堆相当奇怪的内联代码,告诉您真相。我喜欢你想出的方法来决定一个字母是大写还是小写,但剩下的只是 way 当你 random.choice()和上面的 string 常量。

yes_or_no = input("""
Would you like a random password suggestion generated?
Type Yes to continue: """).lower()

您可能没有意识到,在获取用户 input() 之前不需要 print() 描述字符串 - 只需将字符串作为单个参数传递给 input()你会得到同样的效果。我还使用了 triple-quoted """''' 也可以使用)字符串文字,它不同于更常见的单引号 ' 和双引号 " 字符串文字,其中包含的任何换行符或制表符都不需要转义。现在要带回家的是,你可以写几行文本,当你 print() 它时,它会变成几行。

    try:
        pwd_len = int(input('How long do you want your password? '))
    except ValueError:
        sys.exit("You need to enter an integer. Please start the program over.")

我用了一个try/except block for the next part. If the user enters a non-integer up at the input prompt, the int() function will fail with a ValueError。我选择了最简单的处理方式:如果出现错误,打印一条消息并退出。您可以这样做,以便程序在出现错误时重新请求输入,但我认为这超出了本练习的范围。

    if 0 < pwd_len < 26:
        new_pwd = ""
        for _ in range(pwd_len):
            new_pwd += nextchar(possible_chars)
        print("Your new password is:\n" + new_pwd)

    else:
        print("I can only generate passwords between 1 and 25 characters long.")

这里是所有动作发生的地方。使用 if/else 块,我们测试所需的密码长度,如果它在 1 到 25(任意上限)之间,我们将生成密码。这是通过 for 循环和 range() function (read the docs for exactly how it works). You'll notice that I use a common Python idiom in the for loop: since I don't actually need the number generated by range(), I "throw it away" 通过使用下划线 _ 字符代替变量来完成的。最后,else 语句处理替代方案 - pwd_len 等于或小于 0,或者等于或大于 26。

else:
    print("Well then, why did you run me?")

节目快结束了!此 elseif yes_or_no == 'yes': 语句配对 - 用户在输入提示中输入了 yes 以外的内容。

希望这能帮助您更多地了解 Python 的工作原理以及如何使用它进行高效编程。如果您觉得自己花了太多时间来实施您认为应该更容易的事情,那么您可能是对的。 Python 的众多优点之一是它的 "batteries included" 哲学——您可以使用 stdlib 做很多事情。

我做了一些小的修改,我的代码现在似乎可以正常工作了。这是成品(我放了注释以显示代码的作用,并标记编辑。):

import math
import random                                 #Import necessary modules
alpha = ['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']  #List with alphabet
print('Would you like a random password suggestion generator', 'Yes or No')  #Prints the question for permission
permissionRandomGenerator = input().lower()   #Stores the answer of the above question in lower case
if permissionRandomGenerator == 'yes':        #Generates a password if the answer of the first question is 'yes'
print('How long do you want your password?')  #Asks for length
lengthRandomGenerator = int(input())          #Stores length as an integer
    def randInt():                            #Creates a random integer
        return math.floor(random.random()*10)
    def randChar():                          #Selects a random string from the list with the alphabet
        return alpha[math.floor(random.random()*27) - 1]
    randPasswordList = []                    #Creates a list to store the password
    listInsert = 0                           #Creates a list index variable
    def changeCase(f):                       #Defines a function to randomly change the case of letters before adding them to the list randPasswordList
        g = round(random.random())
        if g == 0:
            return f.lower()
        elif g == 1:
            return f.upper()
    while listInsert < lengthRandomGenerator + 1:  #Creates a random password and inserts it into randPasswordList  (I added `+ 1` here)
        randPasswordList.insert(listInsert, randInt())
        listInsert = listInsert + 1
        if listInsert >= lengthRandomGenerator:
            break
        randPasswordList.insert(listInsert, randChar())
        randPasswordList[listInsert] = changeCase(randPasswordList[listInsert])    #Calls the changeCase function whenever it inserts a letter
        listInsert = listInsert + 1
        continue
    listInsert = 0
    printList = 0
    if lengthRandomGenerator <= 0:           #If the length it 0 or less (for example, negatives) the password will not generate (I need to fix this a little bit.  Currently the code attempts to create a password beforehand)
        print('It has to be longer than that')
    elif lengthRandomGenerator >= 25:
        print('I can\'t generate a password that long')
    elif math.isnan(lengthRandomGenerator):  #Currently this doesn't do anything, it needs to be moved farther forward
        print('error: not valid data type')
    else:
        while printList < (len(randPasswordList)-1):    #Prints the list item by item
            printItem = randPasswordList[printList]
            print(printItem)
            printList = printList + 1
    printList = 0                             #Resets the variables
    randPasswordList = []
elif permissionRandomGenerator == 'no':
    print('Too bad...')
else:
    print('You had to answer Yes or No')

注意:我制作这段代码纯粹是为了实验和更好地学习 Python 的基本方面。这段代码没有经过优化,也没有我能(也将)做到的那么随机。

P.S。如果评论不完整请见谅,我还在学习这门语言

我不知道你为什么把这个简单的问题搞得太复杂,你可以使用string对象提供的常量,我宁愿有以下程序来生成随机密码

import random, sys, string

def pgen(length=8):
    if length < 8:
        length = 8 
    keys = list(string.printable[:-6])
    random.shuffle(keys)
    return ''.join(keys)[:length]


if __name__ == '__main__':
    try:
        print( pgen(int(sys.argv[1])))
    except Exception as e:
        print("Provide length of password \n passwordgen.py <length_of_password>")

产出

magautam@nix1947:/tmp$ python passwordgen.py 12
HNLxi!{.qe=b

magautam@nix1947:/tmp$ python passwordgen.py 45
}w5u?+C=e[DfI.n'*1G(m{r0FH|UBKz/@kL>;Sh`tEW8-