Python获取uppCaseList返回bound method而非字母列表问题
问题复现
当前编写的密码生成代码如下:
import random from random import randint as rand upperCase = chr(rand(65,66)) lowerCase = chr(rand(97,122)) class PasswordLetters: def __init__(self): pass def generateCapitalCaseLetter(self): uppCase = chr(rand(65,91)) return uppCase def generateLowerCaseLetter(self): lowCase = chr(rand(97,122)) return lowCase def generateSpecialLetter(self): specLet = random.choice(specialCharacters) return specLet def generateNumber(self): num = rand(1,99) class PasswordGenerator: def __init__(self,uppCase,lowCase,specLet,num): self.uppCaseList = [] lowCaseList = [] specLet = [] numList = [] self.passLetter = PasswordLetters() for i in range(0,uppCase): self.uppCaseList.append(self.passLetter.generateCapitalCaseLetter) password = PasswordGenerator(1,1,1,1) password.uppCaseList
实例化PasswordGenerator后访问uppCaseList属性,得到的列表内存储的是绑定方法对象,而非预期的大写英文字符。
错误原因
核心错误不在PasswordLetters类,而在PasswordGenerator的列表追加逻辑:
- 向
self.uppCaseList追加内容时,写的是self.passLetter.generateCapitalCaseLetter,这行代码只是引用了方法对象本身,没有加括号调用方法执行,所以塞进去的是方法本身,不是方法返回的字符结果。 - 除此之外代码还有几处隐性bug会影响后续运行:
generateNumber方法没有return返回值,调用后会得到NonegenerateSpecialLetter方法引用了未定义的specialCharacters变量,运行会抛出NameErrorPasswordGenerator中定义的lowCaseList、specLet、numList没有加self.前缀,只是构造函数内的局部变量,外部无法访问,且和参数重名会导致逻辑混乱- 最顶部定义的
upperCase、lowerCase变量后续完全没有被使用,属于冗余代码 generateCapitalCaseLetter中随机数右边界设为91,对应字符是[,不属于大写字母范围,会生成不符合预期的字符
修复方案
- 追加方法返回值时,给方法名加括号完成调用,例如
self.passLetter.generateCapitalCaseLetter() - 补全
generateNumber的return语句,提前定义特殊字符集常量 - 给实例属性统一加
self.前缀,修正局部变量和参数重名的问题 - 修正大写字母生成的随机数范围,补全小写字母、特殊字符、数字的生成逻辑
修复后的可运行代码:
import random from random import randint as rand # 提前定义特殊字符集 specialCharacters = "!@#$%^&*()_+-=[]{}|;':\",./<>?" class PasswordLetters: def generateCapitalCaseLetter(self): # randint左右边界都是闭区间,65-90对应大写A-Z uppCase = chr(rand(65,90)) return uppCase def generateLowerCaseLetter(self): # 97-122对应小写a-z lowCase = chr(rand(97,122)) return lowCase def generateSpecialLetter(self): specLet = random.choice(specialCharacters) return specLet def generateNumber(self): num = str(rand(0,9)) return num class PasswordGenerator: def __init__(self, uppCase_count, lowCase_count, specLet_count, num_count): self.uppCaseList = [] self.lowCaseList = [] self.specLetList = [] self.numList = [] self.passLetter = PasswordLetters() # 生成对应数量的大写字母 for _ in range(uppCase_count): self.uppCaseList.append(self.passLetter.generateCapitalCaseLetter()) # 生成对应数量的小写字母 for _ in range(lowCase_count): self.lowCaseList.append(self.passLetter.generateLowerCaseLetter()) # 生成对应数量的特殊字符 for _ in range(specLet_count): self.specLetList.append(self.passLetter.generateSpecialLetter()) # 生成对应数量的数字 for _ in range(num_count): self.numList.append(self.passLetter.generateNumber()) # 如需直接得到拼接好的密码,可以加下面这行 # self.password = ''.join(self.uppCaseList + self.lowCaseList + self.specLetList + self.numList) password = PasswordGenerator(1,1,1,1) print(password.uppCaseList) # 输出示例:['Q']
修复后再访问password.uppCaseList,就能得到由生成的大写字母组成的列表,如果需要打乱字符顺序提升密码强度,可以在拼接密码前对合并后的字符列表做random.shuffle()处理。
内容的提问来源于stack exchange,提问作者user18148692
相关产品推荐
相关产品推荐

