首页 > 解决方案 > 引用 __init__.__kwdefaults__ 与显式编写字典

问题描述

python 3,编码和 python 的新手。我用默认值构建了一个类字典,然后尝试基于该类字典构建一个嵌套字典并遇到了意外行为:

class User:

    def __init__(self, *, name=None, age=None, hobbies=[]):
        self.name = name
        self.age = age
        self.hobbies = hobbies

counter = 0
class_dict = {}

# building the nested dicts with default values
for num in range(0, 3):
    """
    1. referencing "User.__init__.__kwdefaults__"
    vs writting the actual dict directly into the nested dict
    2. {"name": None, "age": None, "hobbies": []}
    """
    class_dict.update({f"key_{num}": User.__init__.__kwdefaults__})
    # class_dict.update({f"key_{num}": {"name": None, "age": None, "hobbies": []}})
print("Blue print: " + str(class_dict))


# updating values in the nested dicts
for x in range(0, 3):   # simplified loop
    dict_key = "key_" + str(counter)
    try:
        if 1 < 2:   # simplified if check
            class_dict[dict_key]["name"] = "updated" + str(counter)
            print("inside loop: " + str(class_dict))
            counter = counter + 1
    except:
        continue

print("<<< final result: " + str(class_dict) + ">>>")  # end-result
  1. User.init.kwdefaults ”版本将按预期更新循环内正确的嵌套dicts键,但最终结果是所有3个嵌套dicts“name”键存储“updated2”作为值。在循环的最后一次迭代中发生的变化在所有嵌套的字典中都会发生变化。

  2. 实际的字典 " {"name": None, "age": None, "hobbies": []} " 版本也会按预期更新循环内正确的嵌套字典键。然而,这里嵌套字典 1 中“名称”键的最终结果存储值“updated0”、嵌套字典 2“upd​​ated1”和嵌套 2“upd​​ated2”。

2. 的最终结果是我的目标,我花了一段时间才找到问题。我不明白为什么两个版本在循环内表现相同但最终结果不同。是否有一个 dunder/magic 方法来引用类字典并获得版本 2. 作为最终结果?

标签: pythondictionarymagic-methods

解决方案


简化为一个最小的示例,您的代码归结为:

d = {'name':None}

dicts = {1: d, 2:d}

print(dicts)
# {1: {'name': None}, 2: {'name': None}}

dicts[1]['name'] = 1
dicts[2]['name'] = 2

print(dicts)
# {1: {'name': 2}, 2: {'name': 2}}

这并不奇怪,因为dicts[1]dicts[2]是同一个 dict d

print(d)
# {'name': 2}

请注意,如果您__init__通过创建 some来调用User(...),而您从未在问题的代码中这样做,您将遇到“最小惊讶”和可变默认参数问题。


推荐阅读