参数是通过引用传递还是通过值传递?如何通过引用传递,以便下面的代码输出“Changed”而不是“Original”?

class PassByReference:
    def __init__(self):
        self.variable = 'Original'
        self.change(self.variable)
        print(self.variable)

    def change(self, var):
        var = 'Changed'

另请参阅:为什么函数可以修改调用者感知的某些参数,而不能修改其他参数?


当前回答

简单答案:

在类似于python的c++中,当您创建一个对象实例并将其作为参数传递时,不会复制实例本身,因此您可以从函数的外部和内部引用相同的实例,并且可以修改相同对象实例的组件基准,因此外部可以看到更改。

对于基本类型,python和c++的行为也相同,因为现在创建了实例的副本,所以外部看到/修改的实例与函数内部不同。因此,外部看不到内部的变化。

下面是python和c++之间的真正区别:

c++具有地址指针的概念,而c++允许您传递指针,这绕过了对基本类型的复制,因此函数内部可以影响与外部相同的实例,因此外部也可以看到更改。这在python中没有等价的,因此如果没有变通方法(例如创建包装器类型)是不可能的。

这样的指针在python中很有用,但不像在c++中那样有必要,因为在c++中,您只能返回一个实体,而在python中,您可以返回用逗号分隔的多个值(即元组)。因此,在python中,如果您有变量a、b和c,并希望函数持久地修改它们(相对于外部),您可以这样做:

a=4
b=3
c=8

a,b,c=somefunc(a,b,c)
# a,b,c now have different values here

这样的语法在c++中是不容易实现的,因此在c++中您可以这样做:

int a=4
int b=3
int c=8
somefunc(&a,&b,&c)
// a,b,c now have different values here

其他回答

问题来自对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'

关于这一点,已经有很多很好的答案(或者说是观点),我已经读过了,但我想提到一个缺失的答案。常见问题解答部分Python文档中的一个。我不知道发布此页面的日期,但这应该是我们的真实参考:

记住,在Python中,参数是通过赋值传递的。自从赋值只创建对对象的引用,没有别名在调用者和被调用者中的参数名之间,因此没有引用调用本身。

如果您有:

a = SOMETHING

def fn(arg):
    pass

你把它叫做fn(a),你做的和你在作业中做的完全一样。所以会发生这种情况:

arg = a

创建了对SOMETHING的其他引用。变量只是符号/名称/引用。他们不“持有”任何东西。

我通常使用的一个简单技巧是将其包装在列表中:

def Change(self, var):
    var[0] = 'Changed'

variable = ['Original']
self.Change(variable)      
print variable[0]

(是的,我知道这可能很不方便,但有时这样做很简单。)

您只能使用空类作为实例来存储引用对象,因为内部对象属性存储在实例字典中。请参见示例。

class RefsObj(object):
    "A class which helps to create references to variables."
    pass

...

# an example of usage
def change_ref_var(ref_obj):
    ref_obj.val = 24

ref_obj = RefsObj()
ref_obj.val = 1
print(ref_obj.val) # or print ref_obj.val for python2
change_ref_var(ref_obj)
print(ref_obj.val)

可以用[]传递

dta=“15252”正文=[dta]