发现一个 python 错误,有人可以解释一下吗?

Found a python bug, can someone explain?

我编写了一个函数来查找两个嵌套词典中的不同键。 answer.

给我很大的启发
    def find_diff_keys(d1: dict, d2: dict, not_included_keys:list = [], path=""):
    for k in d1:
        if k in d2:
            if type(d1[k]) is dict:
                find_diff_keys(d1[k],d2[k],not_included_keys, "%s.%s" % (path, k) if path else k)
        else:
            if type(d1[k]) is dict:
                not_included_keys.append("%s" % path if path else k) # For Root Valuess
                for sub_k in d1[k]:
                    not_included_keys.append("%s.%s" % (k, sub_k))
                continue
            not_included_keys.append("%s.%s" % ("%s" % path if path else "", k))
    return not_included_keys

现在假设我们有两个嵌套字典:a 和 b。 如果我想获得这两个词典的差异,我会 运行 以下内容。请注意,我没有将空列表指定为 not_included_keys 参数...

print("The following keys are included in A but not in B:")
diff_a_to_b = find_diff_keys(ini_dict_a, ini_dict_b)
pprint(diff_a_to_b)
print("")
print("The following keys are included in B but not in A:")
diff_b_to_a = find_diff_keys(ini_dict_b, ini_dict_a)
pprint(diff_b_to_a)

这个输出将是:

The following keys are included in A but not in B:
['FAIL.WEAREDOINGSOMETHING',
 'FAIL.ehh',
 'FAIL.dsa',
 'FAIL.fds',
 'FAIL.gd',
 'FAIL.ewq',
 'TESTVALUE',
 'TESTVALUE.Name',
 'TESTSUBSUB.TestValues2',
 'TESTSUBSUB.TestValues2ltaHz']

The following keys are included in B but not in A:
['FAIL.WEAREDOINGSOMETHING',
 'FAIL.ehh',
 'FAIL.dsa',
 'FAIL.fds',
 'FAIL.gd',
 'FAIL.ewq',
 'TESTVALUE',
 'TESTVALUE.Name',
 'TESTSUBSUB.TestValues2',
 'TESTSUBSUB.TestValues2ltaHz']

现在,如果我 运行 以空列表作为参数的函数:

diff_a_to_b = find_diff_keys(ini_dict_a, ini_dict_b, [])
diff_b_to_a = find_diff_keys(ini_dict_b, ini_dict_a, [])

输出将是:

The following keys are included in A but not in B:
['FAIL.WEAREDOINGSOMETHING',
 'FAIL.ehh',
 'FAIL.dsa',
 'FAIL.fds',
 'FAIL.gd',
 'FAIL.ewq',
 'TESTVALUE',
 'TESTVALUE.Name',
 'TESTSUBSUB.TestValues2',
 'TESTSUBSUB.TestValues2ltaHz',
 'TESTSUBSUB.TestValues2eltaHz']

The following keys are included in B but not in A:
['PointsConfig.130324',
 'ResetAlarm.NotEnabledValue',
 'ResetAlarm.SomeValue',
 'PointsConfig.13032402.Mains.Some_small_difference']

有人能理解为什么在第一种方法中 python 只是复制旧列表,而在第二种方法中函数执行它应该做的事情吗?

不要使用可变对象作为默认参数。(列表、字典等)

改为这样做。

def append_to(element, to=None):
    if to is None:
        to = []
    to.append(element)
    return to

为什么?因为例如列表或字典是可变的,这意味着您在整个代码中编辑相同的引用。 python 在定义函数时创建列表,而不是在调用函数时创建列表,因为函数是 python.

中的第一个 class 公民

更多信息:https://docs.python-guide.org/writing/gotchas/#mutable-default-arguments