为什么Python有时不为函数参数创建新对象?

时间:2015-08-07 19:20:43

标签: python

我认为无论何时将对象传递给函数,它都会自动为您创建一个单独的副本,您可以在不更改原始文件的情况下进行修改。但是,以下代码每次都会以此错误终止。

>>> testvar = ['a' for a in range(100000)]
>>> def func(arg):
        while arg is testvar:
            arg.pop()
>>> func(testvar)
Traceback (most recent call last):
  File "<pyshell#47>", line 1, in <module>
    thing(m)
  File "<pyshell#43>", line 3, in thing
    obj.pop()
IndexError: pop from empty list

2 个答案:

答案 0 :(得分:2)

&#34;我认为无论何时将对象传递给函数,它都会自动为您创建一个单独的副本,您可以在不更改原始文件的情况下进行修改。&#34;

嗯,你的假设是错误的。变量通过引用传递,而不是值。这包括如果您将参数的默认值设置为空列表,并在函数中更改它,下次您尝试使用该默认值时,它将不再是一个空列表。

def foo(bar=[]):
    bar.append("baz")

foo()
foo()
# bar is now ["baz", "baz"]

答案 1 :(得分:2)

来自:https://docs.python.org/3.4/library/copy.html

  

Python中的赋值语句不复制对象,它们在目标和对象之间创建绑定。对于可变或包含可变项的集合,有时需要一个副本,因此可以更改一个副本而不更改另一个副本。该模块提供了通用的浅层和深层复制操作(如下所述)。

当您调用函数时,您正在执行以下操作:

func(arg=testvar)

如果您想拥有数据的实际副本,可以将功能修改为以下内容:

def func(arg):
    arg_copy = arg[:]
    # mutate arg_copy here without mutating arg