使用 for 循环中的局部变量作为字典键的名称会覆盖先前的键

Using local variable from a for loop as name for dictionary key overwrites previous key

当我尝试使用 i+1 向我的字典添加一个值作为我的 for 循环中的名称时,它会替换以前的键,即使它们在技术上具有单独的名称。我目前正在尝试做的是制作一个加密系统,为了做到这一点,我让它随机生成一个关键字,然后将该关键字放入一个列表中,将每个单独的字符分开。这很好用,无论如何我正在使用字典来尝试在一定程度上制作软编码变量。我希望每个字符都有一个变量,以便以后可以引用它们,而不是让很多变量只是从零开始被覆盖。让我向您展示我目前的代码。

import urllib.request
import random

word_url = "http://svnweb.freebsd.org/csrg/share/dict/words?view=co&content-type=text/plain"
response = urllib.request.urlopen(word_url)
long_txt = response.read().decode()
words = long_txt.splitlines()
keyword = random.choice(words)

def split(word):
    return list(word)
def getLetters(word):
    localvar1 = list(word)
    localvar2 = len(localvar1)
    for i in range(localvar2):
        global letters
        letters = {}
        letters[i+1] = localvar1[i].copy()
        print(letters)
def printLetters():
    for i in range(len(letters)):
        try:
            print(letters[1+i])
        except:
            ValueError

这就是所有的代码,这里是专门制作字典的代码。

def getLetters(word):
    localvar1 = list(word)
    localvar2 = len(localvar1)
    for i in range(localvar2):
        global letters
        letters = {}
        letters[i+1] = localvar1[i].copy()
        print(letters)

我认为问题在于它将 i+1 识别为单数名称,即使每次 for 循环时,循环 i 的值都会增加。我已经尝试了我能想到的一切,这是我最后的选择。我几乎查看了所有我能找到的在线文章,尽管我可能遗漏了一些东西。我试过使用 __setitem__ 从该列表创建新列表以及一些我不记得的其他内容。我已经为此工作了几个小时,现在我只是头疼,我们将不胜感激。

它会覆盖变量,因为您在循环中将其重新定义为一个空白字典,然后只将一个值放入其中。将这两行移到循环外,它就修复了。另外你不需要使用那些局部变量,只需要使用枚举。

def getLetters(word):
    global letters
    letters = {}
    for i, letter in enumerate(word, 1):
        letters[i] = letter
    print(letters)

这会打印:

{1: 'W', 2: 'h', 3: 'i', 4: 't', 5: 'c', 6: 'o', 7: 'm', 8: 'b'}

注意我并不完全容忍这种做法,因为这样做非常不合常规。为什么不只是 return 字典并在调用它时将结果分配给一个变量然后现在它是这个上下文中的全局值。同样,一个简单的字典理解也可以完全按照您的意愿进行操作:

def getLetters(word):
    return {i:l for i, l in enumerate(word, 1)}

letters = getLetters(keyword)

编辑 或@furas 如此巧妙地提到,只需使用:

return dict(enumerate(word, 1))

说了这么多,我不相信你真的需要这个功能。要获取此字典中的第二个字母,您可以使用 letters[2] 而如果它只是作为字符串值保留,则可以将其与列表类似地对待,因此 keyword[1] 将是相同的结果,或者只使用keyword[i+1] 如果你必须让第一个索引从 1 开始。