我对如何理解为什么我的密码生成器无法正常执行有疑问

I have questions on how to understand why my password generator is not executing properly

我是一名初级程序员,所以如果我没有注意到显而易见的地方,请原谅我。

我 运行 我的密码生成器有问题。首先,当我 运行 脚本时代码没有正确执行,它打印 "Your password is: ",没有别的,密码不会生成。

我已经检查了带有断点的代码,似乎没有任何异常。我只是需要帮助来解决它无法生成的原因。

再一次,如果我没有注意到'obvious',请原谅我。

谢谢!我的代码如下所示:

import random

Characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
Special_Characters = "~!@#$%^&*()_"
Numbers = "1234567890"
Chosen_Characters = []
Chosen_Special_Characters = []
Chosen_Numbers = []
Password = ""
Nums_amt = 0
S_Character_amt = 0
Character_amt = 0
Total_characters = Nums_amt + S_Character_amt + Character_amt

def Amount_of_Characters():
    num = random.randint(1, 9)
    return(num)

def Character_chooser(A_o_C, Char_amt, Char):
    global Chosen_Characters
    for i in range(A_o_C):
        Chosen_Characters += [random.choice(Char)]
        Char_amt += 1
    return(Chosen_Characters)

def Special_Character_chooser(A_o_C, S_Char_amt, S_Char):
    global Chosen_Special_Characters
    for i in range(A_o_C):
        Chosen_Special_Characters += [random.choice(S_Char)]
        S_Char_amt += 1
    return(Chosen_Special_Characters)

def Number_chooser(A_o_C, Num_amt, Num):
    global Chosen_Numbers
    for i in range(A_o_C):
        Chosen_Numbers += [random.choice(Num)]
        Num_amt += 1
    return(Chosen_Numbers)

def Assembler(A_o_C, C_c, S_C_c, N_c, Total_char, S_Char_amt, Char_amt, Num_amt, Pword):    
    one = random.shuffle(C_c)
    two = random.shuffle(S_C_c)
    three = random.shuffle(N_c)
    for i in range(Total_char):
        chooser = random.randint(1, 3)
        if i + 1 <= Char_amt:
            if chooser == 1:
                temp_num = random.randint(0, len(one))
                Pword += one[temp_num]
                two.pop(temp_num)
        if i + 1 <= S_Char_amt + Char_amt and i + 1 > Char_amt:
            if chooser == 1:
                temp_num = random.randint(0, len(two))
                Pword += two[temp_num]
                two.pop(temp_num)
        if i + 1 > S_Char_amt + Char_amt:
            if chooser == 1:
                temp_num = random.randint(0, len(three))
                Pword += three[temp_num]
                two.pop(temp_num)
    return(Pword)

A = Amount_of_Characters()
B = Character_chooser(Amount_of_Characters(), Character_amt, Characters)
C = Special_Character_chooser(Amount_of_Characters(), S_Character_amt, Special_Characters)
D = Number_chooser(Amount_of_Characters(), Nums_amt, Numbers)

print("Your password is: " + Assembler(A, B, C, D, Total_characters, S_Character_amt, Character_amt, Nums_amt, Password))

TL;DR:您的代码假设如果您将变量传递给函数并更改参数值,它会更改原始值。它没有。这个错误和其他一些错误导致程序失败。

良好的编程风格不仅仅是好看的问题,还在于让其他程序员以及未来的自己更容易阅读您的代码。所以请允许我对您的代码的一些问题发表评论:

  • 您将一个函数命名为 Amount_of_Characters,但您不应在 Python 中的函数名称中使用大写字母,因为它们表示 类,而是将其命名为 amount_of_characters
  • 然后将函数赋值给result A,这实际上并没有做任何事情,但是变量名也应该是小写的,将其命名为a
  • 在对四个单独的函数执行此操作后,您将它们全部传递给另一个函数(同样,大写字母,但你明白了),该函数的参数命名为 A_o_C,完全没有描述性,并且当与 C_cS_C_c 等混合时很难跟踪

不要让您的代码看起来晦涩难懂 - 没有人喜欢它,您将来也不会喜欢它。

查看您的代码后,Amount_of_Characters 似乎只是 return 一个介于 1 和 9 之间的随机整数,Character_chooser 从某个字符串生成一个包含 n 个随机字符的列表, Special_Character_chooser 做了完全相同的事情(除了它们都修改了另一个全局)。 Number_chooser 再次做同样的事情。

具有全局副作用的函数几乎总是设计错误。不是操纵全局变量,只是 return 函数应该产生什么。

您的 Assembler 最终开始打乱随机选择序列的顺序 - 但由于它们已经是随机的,所以这毫无意义。似乎期望像Char_amt这样的变量已经被前面的函数修改了,但实际上它们并没有被声明为global,所以它们没有正确的值。如果他们这样做了,Assembler 似乎 select 从随机字符串中随机选择了一些字符。

所以,最后,您的脚本所做的是:

  • 生成长度为n的字符串
  • 字符串的每个字符都是从三个字符集合(英文字母、数字和一些特殊字符)中以相等的几率随机选择的

因此,此脚本执行完全相同的操作(一旦您开始使用):

import random
from string import ascii_letters, digits


def generate_pass(n):
    chars = ['~!@#$%^&*()_', ascii_letters, digits]
    return ''.join([
        random.choice(chars[random.randint(0, 2)]) for _ in range(n)
    ])


print(generate_pass(10))

脚本中的其他所有内容都只是四处移动并命名。将随机函数重复应用于某事物并不一定会使它更加随机。如果您认为 Python 中的随机库不知何故不够随机,您可以找到更好的库,但对于生成密码的目的,那将毫无意义。

顺便说一句:这是假设您实际上希望密码中的数字、字母和特殊字符的长度相等,否则它可能会更短:

import random
from string import ascii_letters, digits


def generate_pass(n):
    chars = '~!@#$%^&*()_' + ascii_letters + digits
    return ''.join([random.choice(chars) for _ in range(n)])


print(generate_pass(10))

你的错误主要在汇编

错误 1:Total_char、S_Character_amt、Character_amt、Nums_amt

运行这个:

def Assembler(A_o_C, C_c, S_C_c, N_c, Total_char, S_Char_amt, Char_amt, Num_amt, Pword):    
one = random.shuffle(C_c)
two = random.shuffle(S_C_c)
three = random.shuffle(N_c)
print(Total_char)
for i in range(Total_char):
    chooser = random.randint(1, 3)
    if i + 1 <= Char_amt:
        if chooser == 1:
            temp_num = random.randint(0, len(Numbers)-1)
            Pword += Numbers[temp_num]
            two.pop(temp_num)
            print("A")
    if i + 1 <= S_Char_amt + Char_amt and i + 1 > Char_amt:
        if chooser == 1:
            temp_num = random.randint(0, len(Special_Characters))
            Pword += Special_Characters[temp_num]
            two.pop(temp_num)
            print("B")
    if i + 1 > S_Char_amt + Char_amt:
        if chooser == 1:
            temp_num = random.randint(0, len(three))
            Pword += three[temp_num]
            two.pop(temp_num)
            print("C")
print(Pword)
return(Pword)

您会注意到您的 Total_Char 始终为 0,因此 for 循环从未执行过。这是因为您的 Total_characters 首先被定义为 0

Nums_amt = 0
S_Character_amt = 0
Character_amt = 0
Total_characters = Nums_amt + S_Character_amt + Character_amt # 0+0+0

然后打印你所有的其他金额:

print(Total_characters) #0
print(S_Character_amt)  #0
print(Character_amt)    #0
print(Nums_amt)         #0

所以本质上,您正在做的事情的一个例子 运行 是

汇编器(6,['l','Z','w','e','O','K','t'] , ['#', '%', '#', '(', '*', '$', '^', ')'], ['3', '2', '3', '8'], 0, 0, 0, 0, "")

错误 2:随机播放

random.shuffle() 随机播放列表项 returns None 因此一、二和三都是 None 类型

random.shuffle(C_c) 本身就足够了,您可以将汇编程序中的所有内容替换为 C_c 。同样对于两个和三个

错误 3:循环条件

循环索引与字符数组的长度有什么关系?您可能应该只查看数组的长度。如果列表中已经没有任何内容,请跳过。