我有一个字典需要其他函数引用。我并没有把它变成全球性的,而是把字典当作一个论据来传递。
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
的原始字典从未被修改,因此它仍然是空的。传递给functionB
的functionA
中的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
functionA
将dictionary
名称重新分配给与参数中引用的内存不同的新内存。
您的代码在逻辑上等同于:
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()
中的dictionary
和functionA
中的dictionary
视为对同一词典的两个独立引用。重新分配functionA
中的dictionary
时,不会影响main()
中dictionary
的值。根据经验,重新分配只影响放在语句左侧的名称。