这怎么称为Pass By Reference?

tha*_*nce 4 python terminology pass-by-reference pass-by-value

根据教程,Python使用"Pass By Reference".

然后他们继续给出以下示例.在这个"通过参考传递"的星球上?它看起来像是一个明确的"通过价值"案例给我.

思考?

def changeme( mylist ):
   mylist = [1,2,3,4];
   print "Values inside the function: ", mylist
   return

mylist = [10,20,30];
changeme( mylist );
print "Values outside the function: ", mylist
Run Code Online (Sandbox Code Playgroud)

参数mylist是函数changeme的本地.更改函数中的mylist不会影响mylist.该函数什么都不做,最后会产生以下结果:

# Values inside the function:  [1, 2, 3, 4]
# Values outside the function:  [10, 20, 30]
Run Code Online (Sandbox Code Playgroud)

Ama*_*dan 5

两者都不是。是通过共享来调用的。我还听说过“通过参考值传递”这个术语。

\n
\n

共享调用也称为“按对象调用”或“按对象共享调用”,是一种评估策略,最初由 Barbara Liskov 等人命名。1974 年用于 CLU 语言。Python、Iota、Java(用于对象引用)、Ruby、JavaScript、Scheme、OCaml、AppleScript 等语言都使用它。然而,“共享通话”这个词并不常用。不同来源的术语不一致。例如,在 Java 社区中,他们说 Java 是按值调用,而在 Ruby 社区中,他们说 Ruby 是按引用调用,尽管这两种语言表现出相同的语义。通过共享调用意味着语言中的值基于对象而不是基本类型,即所有值都被“装箱”。

\n

共享调用的语义与引用调用不同,因为调用者看不到函数内函数参数的赋值(与引用语义不同),因此,例如,如果传递了一个变量,则不可能模拟一个变量。在调用者的作用域中对该变量进行赋值。但是,由于函数可以访问与调用者相同的对象(不进行复制),因此如果对象是可变的,则函数内这些对象的突变对于调用者来说是可见的,这可能与按值调用不同语义。函数内可变对象的变化对于调用者是可见的,因为该对象不是被复制或克隆的 \xe2\x80\x94 它是共享的。

\n
\n

  • @Serdalis:几乎没有人知道这叫什么,这就是我们一开始陷入困境的原因。:P 大多数课程和教程仍然坚持二元区别,因此人们觉得有必要分配这两个标签之一,即使两者都不合适。 (5认同)

kin*_*all 5

它是值传递,其中所有值都是指向对象的指针.您可能认为这意味着您可以使用传入的指针来更改调用者的变量,使其成为传递引用,但您不能,所以事实并非如此.

理解Python值传递如何工作的关键是知道没有"未装箱"(非对象)值.整数是对象,"包含"整数的变量实际上是指向存储在变量之外的某个整数对象的指针.浮子,布尔,同上.

变量并没有真正"持有"Python中的值,就像它们在C中那样.因此赋值总是包含使变量名称指向不同的对象.

如果传递给函数的对象是可变的,则该函数可以更改它,但必须完全完成此操作而不更改其名称所指向的对象.例如:

some_digits_of_pi = [3, 1, 4, 1, 5, 9, 2, 7]

def extend_pi(x):
    x[-1] = 6
    x += [5, 3, 5, 9]
Run Code Online (Sandbox Code Playgroud)

在这里,我们x在函数内部进行变异.(对于列表,+=本质上是list.extend.)由于x永远不会更改为指向不同的对象,因此对传入的列表进行更改.名称some_digits_of_pi引用与函数中正在修改的对象相同的对象,因此调用者将看到他们的名字列表已被更改.

如果我们x = [2, 7, 1, 8, 2, 8, 1, 8]在函数的末尾写入,那将创建一个新的列表对象并指向x它的本地名称.它不会更改调用者的变量指向的内容,因此该语句不会更改列表.

换句话说,您不能使调用者的变量(some_digits_of_pi在这种情况下)指向不同的对象.如果更改x为指向函数内的其他对象,则仅指x向该对象.

数字,字符串,元组等的工作方式完全相同.传入指向对象的指针; 如果更改函数内部参数的值,则会使其指向另一个对象,这自然不会更改调用者的变量.它似乎有所不同,因为这些类型的对象不可变,并且没有任何方法可以在适当的位置更改它们.

另一个令人困惑的地方是它看起来ints和lists都有+=运算符,但它发生+=在一个int与一个非常不同的东西上list.在列表上,+=返回相同的列表对象(已修改),而在整数上,它可能返回一个完全不同的对象(因为整数是不可变的).