【问题标题】:Python: What is the difference between Call-by-Value and Call-by-Object?Python:按值调用和按对象调用有什么区别?
【发布时间】:2021-12-21 19:52:11
【问题描述】:

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

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

【问题讨论】:

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

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


【解决方案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 中的按值传递的效果区分开来。但从语义上讲,它仍然是按值传递。说变量是“绑定”到对象的“名称”或“句柄”,当你分配或传递它时,你共享对象,完全等同于说变量(事实上, 语言中的所有值)都是指向对象的指针,当你赋值或传递它们时,这些指针是按值复制的。

【讨论】:

  • 非常有趣。谢谢。
猜你喜欢
  • 2022-10-16
  • 2010-10-28
  • 2013-09-01
  • 2014-08-10
  • 1970-01-01
  • 1970-01-01
  • 2011-03-31
相关资源
最近更新 更多