Python字典在某些情况下在函数之间传递时会清空



我有一个字典需要其他函数引用。我并没有把它变成全球性的,而是把字典当作一个论据来传递。

def functionA(dictionary):
dictionary = {}
functionB(dictionary)
print(f"In A, after B, length: {len(dictionary)}")
def functionB(dictionary):
dictionary["A"] = "some value"
dictionary["B"] = "another value"
def main():
dictionary = {}
functionA(dictionary)
print(f"Back in main. Length: {len(dictionary)}")
if __name__ == "__main__":
""" This is executed when run from the command line """
main()

在上面的代码中,main()dictionary初始化为空,并将其传递给functionA(),后者还(冗余地(将其设置为空,然后将其传递到functionB(),后者添加了几个条目。

main()functionA()返回之后,我期望dictionary具有由functionB()添加的两个条目。然而,它是空的。输出为:

In A, after B, length: 2
Back in main. Length: 0

然而,如果我删除functionA中的冗余dictionary = {}(即上述代码块的第二行(,问题就会消失,我得到以下输出:

In A, after B, length: 2
Back in main. Length: 2

我不明白为什么functionA()中的dictionary = {}语句会导致随后添加的项无法传输回main()。有什么见解吗?我觉得这里有一些基本的东西我一无所知。

关键是dictionary = {}不会清空原始字典。相反,它会创建一个新的词典。如果我们将原始字典绑定到另一个名称:,则更容易看到这一点

def functionA(dictionary):
original = dictionary
dictionary = {}
functionB(dictionary)
print(f"In A, after B, length: {len(dictionary)}")
print(f"Original argument: {len(original)}")
In A, after B, length: 2
Original argument: 0
Back in main. Length: 0

main中创建并传递给functionA的原始字典从未被修改,因此它仍然是空的。传递给functionBfunctionA中的dictionary是一个全新的对象(与original分离(,main无法访问,因为它从未是return编辑的。

如果你想通过传递对原始字典的引用来修改它,你需要确保你使用了mutator方法,而不是重新绑定名称,例如:

def functionA(dictionary):
dictionary.clear()
functionB(dictionary)
print(f"In A, after B, length: {len(dictionary)}")
In A, after B, length: 2
Back in main. Length: 2

您还可以通过始终return发送您希望呼叫者接收的任何数据来避免这种类型的混淆:

def functionA(dictionary):
dictionary = {}
dictionary = functionB(dictionary)
print(f"In A, after B, length: {len(dictionary)}")
return dictionary
def functionB(dictionary):
dictionary["A"] = "some value"
dictionary["B"] = "another value"
return dictionary
def main():
dictionary = {}
dictionary = functionA(dictionary)
print(f"Back in main. Length: {len(dictionary)}")
In A, after B, length: 2
Back in main. Length: 2

functionAdictionary名称重新分配给与参数中引用的内存不同的内存。

您的代码在逻辑上等同于:

def functionA(dictionary):
dictionary_a = {}
functionB(dictionary_a)
print(f"In A, after B, length: {len(dictionary_a)}")
def functionB(dictionary):
dictionary["A"] = "some value"
dictionary["B"] = "another value"
def main():
dictionary = {}
functionA(dictionary)
print(f"Back in main. Length: {len(dictionary)}")
if __name__ == "__main__":
""" This is executed when run from the command line """
main()

这应该使问题更加明显。

您可以将main()中的dictionaryfunctionA中的dictionary视为对同一词典的两个独立引用。重新分配functionA中的dictionary时,不会影响main()dictionary的值。根据经验,重新分配只影响放在语句左侧的名称。

最新更新