Python:Call-by-Value和Call-by-Object有什么区别?

时间:2012-06-01 03:38:37

标签: python arguments parameter-passing pass-by-value

许多人说在Python中,函数的参数是使用按值调用的模型传递的。据我了解,它实际上不是一种按值调用的语言,而是一种逐个调用或逐个调用的模型。

按值调用模型和逐个调用模型之间有什么区别? Python中的一个示例显示了这些模型的不同之处?

2 个答案:

答案 0 :(得分:11)

Python中的变量不是值,它们是对象引用。当您调用Python函数时,参数是对原始对象的引用的副本。我不知道这与你在问题中提出的术语有什么关系。

例如,请考虑以下Python代码:

def foo(bar, baz):
    bar = 3
    baz[0] = 4

a = 1
b = [2]
foo(a, b)
print a, b

a已分配给对象1b已分配给包含对象2的引用的列表对象。在函数foo内部,bar也被分配给同一个对象1baz被分配给同一个列表对象。由于1是不可变的,因此您无法更改对象,但您可以重新指定bar以引用其他对象,例如3。列表是可修改的,因此通过将baz[0]设置为4,您还可以更改b引用的列表对象。以上输出为1 [4]

答案 1 :(得分:8)

说它不是按值传递是不正确的。从语义上讲,值传递,并且可以证明它与其他传值值语言之间的语义等价。但是,它属于值为pass-by-value语言的特定子类别,其中所有值都是对象的引用(指针)(您不能将对象直接作为值),并且许多人将指向对象的指针与对象混淆本身。这些语言包括Java(关于对象),Python,Ruby,JavaScript,Scheme,Smalltalk,仅举几例。

令人困惑的是,不同语言的社区使用不同的术语。例如,Java社区始终将Java描述为按值传递,即使Java中的对象与Python和Ruby中的对象具有完全相同的语义。但是,在后面这些语言的社区中,你会听到“价值传递”。

按值传递与传递引用本质上是一种语义区别,而不是它的用途。但是许多(初学者)程序员并不关心语义,更关心它可以用来做什么。例如,有些人认为,只要你有“我有一些数据,我给一个函数,它可以改变它而不返回它,我可以看到变化”,这意味着传递引用,而不是实际思考(关于改变的东西是你所经过的东西,还是你通过的东西间接指出的东西。

“按对象传递”或“通过共享传递”或任何用于描述传值语义组合以及使所有值都为引用(指针)的术语。以这种方式,它们可以更容易地表达这种组合的实际效果,并且例如将其与C中的值传递的效果区分开。但从语义上讲,它仍然是价值传递。说变量是“绑定”到对象的“名称”或“句柄”,当你分配或传递它时,你共享对象,完全等同于来表示变量(事实上) ,语言中的所有值都是指向对象的指针,当您指定或传递它们时,这些指针将按值复制。