Python:按值调用和按对象调用有啥区别?

Posted

技术标签:

【中文标题】Python:按值调用和按对象调用有啥区别?【英文标题】:Python: What is the difference between Call-by-Value and Call-by-Object?Python:按值调用和按对象调用有什么区别? 【发布时间】:2012-06-06 07:54:17 【问题描述】:

很多人说,在 Python 中,函数的参数是使用按值调用模型传递的。据我了解,它实际上不是按值调用的语言,而是按对象调用或按共享调用的模型。

按值调用模型和按对象调用模型之间有什么区别?什么是 Python 中的示例,可以显示这些模型的不同之处?

【问题讨论】:

它是“按引用传递”或“按值传递” 还有“call-by-reference”和“call-by-value”。 我更喜欢将其视为“引用值调用” @gnibbler - 你的意思是专门指 Python? @cytinus,是的,虽然它也可能适用于其他语言。 【参考方案1】:

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]

【讨论】:

精彩的解释。特别是对象引用概念。【参考方案2】:

说它不是按值传递是不正确的。从语义上讲,它传值方式,可以证明它与其他传值方式语言的语义等价性。但是,它属于按值传递语言的特定子类别,其中所有值都是对象的引用(指针)(您不能直接将对象作为值),并且许多人将指向对象的指针与对象混淆本身。此类语言包括 Java(就对象而言)、Python、Ruby、javascript、Scheme、Smalltalk 等等。

更令人困惑的是,不同语言的社区使用不同的术语。例如,Java 社区一直将 Java 描述为按值传递,尽管 Java 中的对象与 Python 和 Ruby 中的对象具有完全相同的语义。但是,在后面这些语言的社区中,您听到的“按值传递”要少得多。

按值传递与按引用传递本质上是语义上的区别,而不是它的用途之一。但是许多(初学者)程序员并不太关心语义,而更关心它可以用来做什么。例如,有些人认为每当你有“我有一些数据我给一个函数,它可以改变它而不返回它,我可以看到变化”,这意味着传递引用,没有真正思考(或关心)改变的东西是你传递的东西,还是你传递的东西间接指向的东西。

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

【讨论】:

非常有趣。谢谢。

以上是关于Python:按值调用和按对象调用有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

C/C++按值传递和按地址传递

引用传递和引用调用有啥区别?

VB 参数传递:按值传递和按地址传递

C#在方法调用中,参数按值传递与按引用传递的区别是啥?

oracle中按级别连接和按先验连接有啥区别?

HashMap按键排序和按值排序