如何在不使用全局变量的情况下构建此程序?

2024-10-01 02:18:47 发布

您现在位置:Python中文网/ 问答频道 /正文

我刚刚创建了我的第一个Python项目。我确信有很多改进可以做,但我有一个关于如何修改代码的具体问题

我一直在读到使用全局变量是不明智的(出于安全考虑)。但我不知道如何使多个函数一起工作(即使用相同的变量),除非它们是全局的

下面的程序有三个功能:

  1. 生成密码
  2. 加密那个密码
  3. 解密密码

但是,我在第2部分中只声明了全局变量来加密密码

我的问题是:如何修改代码以避免使用全局变量?我已经粘贴了下面的所有代码以供参考,但是globals是在def listToString()def passEncryptor():中声明的

import random

#variables to hold a list and a string
Password = []
Encrypted = ''

#variables to hold the specific characters
#to use in creating the password
a = 'abcdefghijklmnopqrstuvwxyz'
b = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
c = '0123456789'
d = '!@#$%^&*()'

#variable holds all possible values
#that could be found in the password
e = a + b + c + d

#variables will randomize the password length
sm = random.randint(2,3)
lg = random.randint(3,4)

#function generates a randomized password
def passwordGenerator() :

    #append elements from variables a - d
    #to the Password variable
    for x in range(sm) :
        Password.append(random.choice(a))
    for x in range(sm) :
        Password.append(random.choice(b))
    for x in range(lg) :
        Password.append(random.choice(c))
    for x in range(sm) :
        Password.append(random.choice(d))

    #randomize the order of the elements    
    random.shuffle(Password)

    #ensure the first element is a letter
    Password.insert(0, random.choice(a))

    #print to show that the program worked
    print(Password)

#call function to generate a randomized password
passwordGenerator()

#function to store 5 random elements in a string
def listToString() :

    #can't seem to get this to work
    #without using a global variable
    global rand5
    rand5 = ''
    x = random.choices(e, k=5)
    for val in x :
        rand5 += val
    return rand5

#for each element in the password
#add the random 5 elements from listToString()
def passEncryptor():

    global tempPass
    tempPass = ''
    for val in Password :

        #gets 5 new random elements
        listToString()

        #concatenate the random elements
        #with the real password
        tempPass += val + rand5

    print(tempPass)
passEncryptor()

#function to unencrypt an encrypted password
def passDecryptor():

    #convert the encrypted string to a list
    encryptedList = []
    for val in tempPass :
        encryptedList.append(val)

    #remove the random 5 elements    
    decrypt = encryptedList[::6]
    decrypted = ''
    #convert back to a string
    for val in decrypt :
        decrypted += val

    print(decrypted)

passDecryptor()

Tags: thetoin密码fordefrandomval
2条回答

创建一个class并将函数作为类方法,变量作为该类的成员

在这种情况下,这实际上是因为缺乏知识-你没有利用函数参数-我假设你不知道它们是什么,因为如果你知道,你会更喜欢它们而不是全局变量

我不知道“安全性”正是使用全局变量时要牺牲的东西。当然,我可以想到一些假设的例子,我相信有人可以举出一些真实的例子,其中使用全局变量是一个主要的安全问题。。。我的意思是,使用全局变量并不会使您的程序本质上不安全——只是很容易错误地使用它们(有正确的方法吗?)。有更好的解决方案可以解决您认为只有使用全局变量才能解决的问题

您发布的代码实际上完美地演示了全局变量的关键-如果我,您程序的用户,想要生成多个密码,我得到的结果是出乎意料的:

['d', 'q', '3', 'O', 'g', '1', '$', 'J', '&', '7']
dsLT(mq4N^Yy3(L)%iOr&VM3gTfaZq1&ud9B$RJJ1aJe6Nju&O2*rE7Zz@Y!
dq3Og1$J&7
>>> passwordGenerator()
['n', '&', 'E', ')', '7', '0', '&', 'O', '2', '1', '$', '3', 'q', 'q', 'k', 'J', 'B', '1', 'd', 'g']
>>> passwordGenerator()
['j', '9', 'd', '1', 'k', 'O', 'B', 'q', 'Q', '2', 'g', 'o', 'e', '7', '1', 'n', 'q', '$', 'J', '&', '!', '0', 'A', '!', 'E', ')', '3', '7', '&', '2']
>>> passwordGenerator()
['u', 'o', '!', ')', '0', 'j', 'h', '1', '!', 'q', '7', 'g', '$', '9', 'n', 'k', 'q', '1', '&', 'd', 'J', '2', 'B', '8', '3', '2', '&', '7', 'L', '*', 'O', '5', 'Q', 'e', '&', 'S', '2', 'E', 'A', 'x']
>>> passwordGenerator()
['o', 'h', 'u', '1', 'S', 'q', '&', '7', '$', 'g', '7', '8', '2', '3', 'J', '&', 'k', 'A', '9', 'q', '2', '1', '6', 'B', '0', '*', '&', '!', 'e', 'x', 'j', 'B', 'L', 'a', 'o', '9', ')', '$', 'n', '9', 'U', 's', '!', 'Q', 'E', '2', 'd', '&', '5', 'O']

passwordGenerator通过在每次调用函数时向全局变量Password添加元素来修改该变量的状态。一般来说,函数会意外地修改变量的状态(恰好位于函数范围之外)。这就是为什么全局变量可能是问题的根源,无论是安全性还是其他方面

这是不相关的,但您也在做一些不必要的事情,比如在添加随机字符后对Password进行洗牌。下面是函数参数的外观:

def get_random_password(alphabet):
    from random import randint, choices

    password_length = randint(5, 16)
    password = choices(alphabet, k=password_length)

    return "".join(password)


def get_encrypted(alphabet, plaintext):
    from random import choices

    return "".join(char + "".join(choices(alphabet, k=5)) for char in plaintext)

def get_decrypted(encrypted_plaintext):
    return encrypted_plaintext[::6]

def main():
    import string

    alphabet = string.digits + string.ascii_letters + string.punctuation
    # alphabet = string.printable.rstrip()

    password = get_random_password(alphabet)
    encrypted = get_encrypted(alphabet, password)
    decrypted = get_decrypted(encrypted)

    print(f"The password is \"{password}\"")
    print(f"Encrypted: \"{encrypted}\"")
    print(f"Decrypted: \"{decrypted}\"")


if __name__ == "__main__":
    main()

输出:

The password is "O*L7~"
Encrypted: "OiL)V\*I={w&LX5"2-7WF/\+~5%_mP"
Decrypted: "O*L7~"
>>> 

我还添加了一个入口点main,并进一步利用了标准库。这是相切的,但严格来说,您并不是真正的“加密”字符串——它更像是模糊处理,但不管怎样

相关问题 更多 >