当你在Python中将像列表、数组这样的集合传递给另一个函数时,它是制作副本还是只是指针?
当你在Python中将像列表、数组这样的集合传递给另一个函数时,它是制作副本还是只是指针?
Python以传值方式传递对象的引用(像Java一样),而且Python中的所有东西都是对象。这听起来很简单,但你会注意到有些数据类型似乎表现出了传值的特性,而另一些似乎像是传引用……怎么回事呢?
理解可变和不可变对象很重要。一些对象,比如字符串、元组和数字,是不可变的。在函数/方法内部修改它们将创建一个新实例,而函数/方法外部的原始实例不会被改变。另一些对象,比如列表和字典,是可变的,这意味着你可以就地更改对象。因此,在函数/方法内部修改对象也会改变函数/方法外部的原始对象。
事实上,整个引用和值的概念并不适用于Python。Python没有变量的“值”,只有对象和指向对象的名称。
因此,当你调用一个函数并在括号中放入一个“名称”时,像这样:
def func(x): # defines a function that takes an argument
... # do something here
func(myname) # calling the function
传递的是myname
指向的实际对象,而不是myname
本身。在函数内部,给定另一个名称x
来引用传递的同一对象。
如果可变,您可以在函数内部修改对象,但无法更改外部名称所指向的内容。当执行以下操作时同样会发生这种情况:
anothername = myname
因此,我可以回答你的问题:它是"按值传递",但所有的值都只是对象的引用。locals()
时,这通常是不必要的。是的,Java有几种原始类型,而Python只有一种。 - Elazar这里的回答很有帮助,但我觉得需要展示这个细微的区别,我没有看到过相关的涵盖,我通过后续的CL实验证明了这一点:
这里的“num”没有改变,因为它是一个不可变的数字对象[支持我的第一点]:
>>> def incr_num(num):
num += 1
>>> num = 0
>>> num
0
>>> incr_num(num)
>>> num
0
list[0]
这里也是一个不可变的数值对象。
>>> def incr_list(list):
list[0] += 1
>>> list = [0]
>>> list[0]
0
>>> incr_list(list)
>>> list[0]
1
那么,作为一个不可变的数字对象,list[0]
是如何改变(支持我的第二点)而上面例子中的数字对象“num”没有改变呢? 不可变的数字对象list[0]
被包含在可变的列表对象“list”中,而第一个例子中的“num”只是一个非包含的数字对象(不可变的)。
虽然出于好意,我认为@Stephen Pape的最高评分答案(如下所引用)以及其他类似的答案并不完全正确(这促使我撰写了这篇答案):
某些对象,如字符串、元组和数字,是不可变的。在函数/方法内部修改它们将创建一个新实例,函数/方法外部的原始实例不会改变。
我上面的第二个代码实验展示了在方法内部更改数字对象(“list[0]”),然后函数外部的原始实例也被更改了。
虽然传递的是引用,但如果参数是一个不可变对象,在方法内部修改它将创建一个新实例。
通过引用:
>>> x = [0,1,2,3]
>>> def foo(x_list):
x_list[0] = 1
>>> foo(x)
>>> x
[1, 1, 2, 3]
请允许我举一个简单的例子
def swap(a, b):
x = a
print id(x)
print id(a)
print id(b)
a = b
print id(a)
b = x
print id(b)
a[0]= '20'
var1 = ['1','2','3','4']
var2 = ['5','6','7','8','9']
print id(var1)
print id(var2)
swap(var1, var2)
print id(var1)
print id(var2)
print var1
print var2
产生以下结果
28329344 var1 28331264 var2 28329344 x 28329344 a 28331264 b a = b 后 28331264 a b = x 后 28329344 b 返回后 28329344 var1 28331264 var2 ['1', '2', '3', '4'] ['20', '6', '7', '8', '9']
映射到内存地址 28329344 28331264 var1 var2 a b x a=b 后 a b=x 后 b a[0] = '20' 后 [0] = '20' 返回后 ['1','2','3','4'] ['20', '6', '7', '8', '9']