繁体   English   中英

为什么Python中的列表参数表现得像ByRef?

[英]Why Does List Argument in Python Behave Like ByRef?

一般来说,这可能适用于大多数语言,但是我不确定。 我是Python的初学者,一直致力于C#和VB中的列表副本。 但是在Python中,每当我将列表作为参数传递并使用“ for i in range”进行枚举,然后更改list参数的值时,输入值实际上会更改原始列表。 我以为Python应该默认通过值传递参数,因此一旦函数完成,我仍然拥有调用该函数之前的原始值。 我想念什么? 谢谢!

Python确实通过值传递参数,但是您收到的值是引用的副本(顺便说一下,这与C#,VB.NET和Java的行为完全相同)。

这是要记住的重要事项:

引用不传递对象-引用按值传递对象

由于您具有参考的副本,因此对该参考所指向的内容进行的任何操作都将如同您拥有原始参考本身一样。

Python –就像Java除了原始标量之外,对其他所有东西都适用,而C#和VB.NET与默认类型参数(而不是盒装类型和out / ref parms)一样,都通过“按对象引用”传递( 在此处搜索该短语) -这就是Python的架构师和创建者Guido用来解释这个参数传递概念的方式。

每个名称都是对某个对象的引用; 传递名称(或任何其他表达式)作为参数只是在创建对同一对象的另一个引用(函数主体可以通过参数的名称来访问该对象)。 ((没有“对名称的引用”之类的东西:存在名称 ,这是对对象的一种引用,即对象-句点))。

当您传递可变对象时,即具有可变方法(例如列表)的对象时,被调用函数可以通过直接或间接调用其可变方法来使对象可变。 ((((“间接”是指“通过运算符”,例如:

somelist[len(somelist):] = [whatever]

somelist.append(whatever)完全相同。))

当您希望将列表传递给函数但希望函数能够以任何方式使该列表发生变异时,则必须传递列表的副本而不是原始副本 ,就像在Java,C#,VB中一样。净。

关于重新绑定名称更改对象之间的区别要非常清楚。 重新绑定名称(“裸名”,即-限定名称不同;-) 影响该名称 - 不会影响任何对象。 例如:

def f1(alist):
  alist = [23]

def f2(alist):
  alist[:] = [23]

您能发现这两个功能之间的区别吗? 一是重新绑定barename alist -没有任何东西上的任何影响。 另一种是通过将其内容设置为一个以int为唯一项的单项列表来更改(更改,更改等)它作为参数接收的列表对象。 完全不同的事情!!!

要添加到安德鲁的答案中,如果您想保留原始列表,则需要显式复制列表。 您可以使用copy模块执行此操作,也可以执行类似的操作

a = [1,2]
b = list(a)

由于复制对象通常意味着性能下降,因此我发现在较大的项目中显式使用复制模块会有所帮助。 这样,我可以轻松找到将要使用更多内存的所有位置。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM