1

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

4

3 回答 3

8

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

这是要记住的重要事项:

对象不是按引用传递的——对象引用是按值传递的

由于您拥有参考的副本,因此对该参考指向的任何操作都将就像您持有原始参考本身一样。

于 2009-10-09T03:17:09.150 回答
4

Python——就像 Java 对原始标量所做的任何事情一样,就像 C# 和 VB.NET 对默认类型参数所做的那样,而不是盒装类型和 out / ref 参数——传递“按对象引用”(在此处搜索该短语——这就是 Python 的架构师和创建者 Guido 用来解释这个参数传递概念的方式)。

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

当您传递一个可变对象时,即具有可变方法的对象(例如列表),被调用函数可以通过直接或间接调用其可变方法来改变对象。((通过“间接”,我的意思是“通过运营商”——例如:

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

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

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

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

def f1(alist):
  alist = [23]

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

你能看出这两个函数的区别吗?一个是重新绑定barename—— alist对任何东西都没有任何影响。另一个是改变(改变、改变……)它作为参数接收的列表对象——通过将其内容设置为一个单项列表,其中一个 int 作为其唯一项。 完全不同的东西!!!

于 2009-10-09T03:44:07.037 回答
0

要添加到 Andrew 的答案,如果您想保留原件,您需要明确制作一份列表的副本。您可以使用copy模块执行此操作,或者只是执行类似的操作

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

由于复制对象通常意味着性能下降,我发现在我的大型项目中明确使用复制模块很有帮助。这样,我可以很容易地找到我将要使用更多内存的所有地方。

于 2009-10-09T03:26:44.433 回答