参数是通过引用传递还是通过值传递?如何通过引用传递,以便下面的代码输出“Changed”而不是“Original”?
class PassByReference:
def __init__(self):
self.variable = 'Original'
self.change(self.variable)
print(self.variable)
def change(self, var):
var = 'Changed'
另请参阅:为什么函数可以修改调用者感知的某些参数,而不能修改其他参数?
(编辑-布莱尔更新了他广受欢迎的答案,使其准确无误)
我认为重要的是要注意到,目前获得最多选票的帖子(布莱尔•康拉德),虽然其结果正确,但却具有误导性,并且根据其定义,几乎不正确。虽然有许多语言(如C)允许用户通过引用传递或通过值传递,但Python不是其中之一。
大卫·库尔纳波的回答指向了真正的答案,并解释了为什么布莱尔·康拉德帖子中的行为似乎是正确的,而定义却不正确。
在Python是按值传递的情况下,所有语言都按值传递,因为必须发送一些数据(无论是“值”还是“引用”)。然而,这并不意味着Python是按C程序员会想到的值传递的。
如果你想要这种行为,Blair Conrad的回答很好。但如果你想知道Python既不是通过值传递,也不是通过引用传递的根本原因,请阅读大卫·库尔纳波的答案。
问题来自对Python中变量的误解。如果你习惯了大多数传统语言,你会有一个心理模型来描述以下顺序:
a = 1
a = 2
您认为a是存储值1的内存位置,然后更新为存储值2。这不是Python中的工作方式。相反,a开始作为对值为1的对象的引用,然后重新分配为对值为2的对象的参考。这两个对象可能会继续共存,即使a不再指代第一个对象;事实上,它们可以由程序内的任何数量的其他引用共享。
使用参数调用函数时,将创建一个引用传入对象的新引用。这与函数调用中使用的引用不同,因此无法更新该引用并使其引用新对象。在您的示例中:
def __init__(self):
self.variable = 'Original'
self.Change(self.variable)
def Change(self, var):
var = 'Changed'
self.variable是对字符串对象“Original”的引用。当调用Change时,将创建对象的第二个引用变量。在函数内部,您将引用变量重新分配给不同的字符串对象“Changed”,但引用self.variable是独立的,不会更改。
解决此问题的唯一方法是传递一个可变对象。因为两个引用都引用同一个对象,所以对对象的任何更改都会反映在两个位置。
def __init__(self):
self.variable = ['Original']
self.Change(self.variable)
def Change(self, var):
var[0] = 'Changed'