【问题标题】:Dictionary changes without obvious reason没有明显原因的字典更改
【发布时间】:2020-02-27 22:07:23
【问题描述】:

出于学习原因,我正在尝试创建一个琐事游戏,但是我的字典发生了一些我无法理解的奇怪问题。

我通常测试的代码是这样的:

cat = {
    'easy': {
        'books': 'https://opentdb.com/api.php?amount=50&category=10&difficulty=easy&type=boolean',
        'films': 'https://opentdb.com/api.php?amount=50&category=11&difficulty=easy&type=boolean',
        'general knowledge': 'https://opentdb.com/api.php?amount=50&category=9&difficulty=easy&type=boolean',
        'music': 'https://opentdb.com/api.php?amount=50&category=12&difficulty=easy&type=boolean',
        'science & nature': 'https://opentdb.com/api.php?amount=50&category=17&difficulty=easy&type=boolean',
        'sports': 'https://opentdb.com/api.php?amount=50&category=21&difficulty=easy&type=boolean'
    },
    'medium': {
        'books': 'https://opentdb.com/api.php?amount=50&category=10&difficulty=medium&type=boolean',
        'films': 'https://opentdb.com/api.php?amount=50&category=11&difficulty=medium&type=boolean',
        'general knowledge': 'https://opentdb.com/api.php?amount=50&category=9&difficulty=medium&type=boolean',
        'music': 'https://opentdb.com/api.php?amount=50&category=12&difficulty=medium&type=boolean',
        'science & nature': 'https://opentdb.com/api.php?amount=50&category=17&difficulty=medium&type=boolean',
        'sports': 'https://opentdb.com/api.php?amount=50&category=21&difficulty=medium&type=boolean'
    }
}

print(cat)

for level in cat:
    print(level)

catselect = []
while catselect not in ("1", "2"):
    catselect = input("Select a category, for easy press 1, for medium press 2: ")

    if catselect == "1":
        selectedcat = "easy"
    elif catselect == "2":
        selectedcat = "medium"
    print(f"You selected the {selectedcat} difficulty level")

    print("The subjects can be: ")
    for i, cat[selectedcat] in enumerate(cat[selectedcat]):
        print(i, cat[selectedcat])

print(cat)

所以当最后代码运行时,猫字典是不一样的 更多,我没有任何理由会发生这种情况。

这是我看到的:

{'easy': {'books': 'https://opentdb.com/api.php?amount=50&category=10&difficulty=easy&type=boolean', 'films': 'https://opentdb.com/api.php?amount=50&category=11&difficulty=easy&type=boolean', 'general knowledge': 'https://opentdb.com/api.php?amount=50&category=9&difficulty=easy&type=boolean', 'music': 'https://opentdb.com/api.php?amount=50&category=12&difficulty=easy&type=boolean', 'science & nature': 'https://opentdb.com/api.php?amount=50&category=17&difficulty=easy&type=boolean', 'sports': 'https://opentdb.com/api.php?amount=50&category=21&difficulty=easy&type=boolean'}, 'medium': {'books': 'https://opentdb.com/api.php?amount=50&category=10&difficulty=medium&type=boolean', 'films': 'https://opentdb.com/api.php?amount=50&category=11&difficulty=medium&type=boolean', 'general knowledge': 'https://opentdb.com/api.php?amount=50&category=9&difficulty=medium&type=boolean', 'music': 'https://opentdb.com/api.php?amount=50&category=12&difficulty=medium&type=boolean', 'science & nature': 'https://opentdb.com/api.php?amount=50&category=17&difficulty=medium&type=boolean', 'sports': 'https://opentdb.com/api.php?amount=50&category=21&difficulty=medium&type=boolean'}}
easy
medium
Select a category, for easy press 1, for medium press 2: 1
You selected the easy difficulty level
The subjects can be: 
0 general knowledge
1 books
2 films
3 music
4 sports
5 science & nature
{'easy': 'science & nature', 'medium': {'general knowledge': 'https://opentdb.com/api.php?amount=50&category=9&difficulty=medium&type=boolean', 'books': 'https://opentdb.com/api.php?amount=50&category=10&difficulty=medium&type=boolean', 'films': 'https://opentdb.com/api.php?amount=50&category=11&difficulty=medium&type=boolean', 'music': 'https://opentdb.com/api.php?amount=50&category=12&difficulty=medium&type=boolean', 'sports': 'https://opentdb.com/api.php?amount=50&category=21&difficulty=medium&type=boolean', 'science & nature': 'https://opentdb.com/api.php?amount=50&category=17&difficulty=medium&type=boolean'}}

easy 的所有类别都去了哪里?为什么我最终会选择'science & nature'

【问题讨论】:

  • 是不是字典项的顺序变了?如果是这样,那是因为 python 中的字典本身的结构方式,因为它们不保留您最初给它们的插入顺序。内置的 python 字典是一个键值查找表。您的案例问题类别中的键是散列的,不保持顺序。如果顺序很重要,可以查看集合库中的 OrderedDicts。
  • @darcycp:不,这不是字典排序问题。我更新了问题以包含输出以更好地说明发生了什么。此外,从 Python 3.6 及更高版本开始,字典确实保留插入顺序。

标签: python dictionary printing


【解决方案1】:

您在此处分配回字典:

for i, cat[selectedcat] in enumerate(cat[selectedcat]):

您要求for 循环分配给i cat[selectedcat]。不要那样做。

上面基本上是这样做的:

iterator = iter(enumerate(cat[selectedcat]))
while True:
    try:
        next_item = next(iterator)
    except StopIteration:
        break
    i, cat[selectedcat] = next_item

因此将每个值从cat[selectedcat] 分配给cat[selectedcat] 本身

它恰好起作用,因为 cat[selectedcat] 引用的原始字典仍然被 enumerate() 对象引用,因此它的所有键仍在循环中生成。但是cat 字典本身被要求用每个类别字符串依次替换selectedcat 键的值。您可以看到这种情况发生,因为您随后在循环内 打印 cat[selectedcat] 的新值。

如果你想用数字显示值,你想为循环使用不同的新变量名,例如:

for i, category in enumerate(cat[selectedcat]):
    print(i, category)

这里,category 是一个新变量(就像 i 一样)。

【讨论】:

  • 感谢您的评论!非常感谢你! :)
【解决方案2】:

问题出在这一行:

    for i, cat[selectedcat] in enumerate(cat[selectedcat]):

每次循环都会将cat[selectedcat] 的元素分配给cat[selectedcat],从而修改字典。所以第一次通过循环,它确实

cat[selectedcat] = cat[selectedcat][0]

当循环完成时,cat[selectedcat] 的值将是cat[selectedcat] 的最后一个元素。

您通常应该为循环变量使用普通变量:

for i, value in enumerate(cat[selectedcat]):
    print(i, value)

【讨论】:

  • 嗨。感谢您的快速回答以及发生这种情况的原因!我真的很感激:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-26
  • 1970-01-01
  • 1970-01-01
  • 2020-07-09
  • 2013-01-14
相关资源
最近更新 更多