我开始学习Python,并开始尝试一个示例代码块。我对它进行了几次编辑,在最后一次编辑时,我添加了一个可选的随机密码生成器。然后我决定将密码生成器放在一个单独的文档中更有意义,所以我复制了必要的代码并制作了一个新文档。然而,编辑后,我无法在密码中生成偶数位数。
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不仅仅是语法和内置函数,它还是标准库或stdlib。您将一直使用stdlib的模块,所以当您认为要使用stdlib模块时,请阅读文档您将了解该模块,它的预期用途,它的一些历史和更改(例如在哪个版本中添加了某个函数),以及其中包含的所有类、函数和属性。确保你读了整件事(没有一件是那么长),并试着至少对每件事的作用有一个基本的了解。这样,例如在这种情况下,您将能够为工作选择最佳功能。我喜欢在业余时间做的一件事就是随便挑选一个模块,阅读文档,只是为了学习。它们通常写得很好,通常也很包容。习惯Monty Python引用,它们无处不在。
import random
import string
import sys
进口是第一位的,而且几乎总是应该排在首位。我喜欢按字母顺序排列我的模块,stdlib在上面,然后是一行空白,然后是第三方模块,包括下面的自写模块。在进口商品后也加上一两行空白。有一件事需要记住,我在评论中提到:可读性很重要。代码不仅意味着机器可以读取,也意味着人可以读取。必要时进行评论。要慷慨使用空格(还要记住,空格在Python中在语法上也很重要,所以它迫使你正确缩进),以分离代码、函数、类、块等的相关部分。我强烈建议你阅读、重读并花时间思考Python风格指南PEP-8。它的建议并不是绝对的,但许多实施编码标准的项目都依赖它。尽可能多地遵循它。如果一行有83个字符,不要担心,但要注意你在做什么。
我之所以如此重视阅读文档,是因为以下几行:
possible_chars = string.ascii_letters + string.digits + string.punctuation
def nextchar(chars):
return random.choice(chars)
他们会删除大约一半的代码。string
包含一组用于处理字符串的预定义常量。我选择的三个字符都应该是有效的密码字符。如果你所在的系统不接受标点符号,只需删除它。注意,possible_chars
是一个字符串,就像元组、列表和dicts一样,字符串是可迭代的,所以你不需要为每个可能的字符单独列出一个列表。
接下来是函数——它替换了randInt()
、randChar()
和changeCase()
函数,以及一堆内联代码,说实话,这很奇怪。我喜欢你提出的决定一个字母是大写还是小写的方法,但当你有random.choice()
和string
常量时,剩下的都太费力了。
yes_or_no = input("""
Would you like a random password suggestion generated?
Type Yes to continue: """).lower()
您可能没有意识到,但在获得用户input()
之前,您不需要print()
一个描述字符串——只需将该字符串作为单个参数传递给input()
,您就会获得相同的效果。我还使用了一个三引号"""
(也可以使用'''
)字符串文字,它与更常见的单引号'
和双引号"
字符串文字的不同之处在于,其中包含的任何换行符或制表符都不需要转义。现在要记住的是,你可以写几行文本,当你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
块。如果用户在输入提示符处输入一个非整数向上,则int()
函数将以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()
函数完成的(请阅读文档以了解它的确切工作方式)。您会注意到,我在for
循环中使用了一个常见的Python习惯用法:因为我实际上不需要range()
生成的数字,所以我使用下划线_
字符代替变量来"丢弃"它。最后,else
语句处理备选方案——pwd_len
为0或更小,或者为26或更大。
else:
print("Well then, why did you run me?")
我们的节目结束了!此else
与if yes_or_no == 'yes':
语句配对—用户在输入提示符处输入了yes以外的内容。
希望这能帮助你更多地了解Python是如何工作的,以及如何使用它进行高效编程。如果你觉得你花了太多时间来实现一些你认为应该更容易的东西,那你可能是对的。Python的许多优点之一是其"包含电池"的理念——您可以使用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的基本方面。这个代码没有优化,也没有像我能(也将)做的那样随机
附言:很抱歉,如果评论不完整,我仍在学习这门语言。
我不知道你为什么要为这个简单的问题做过于复杂的事情,你只需要使用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-