当您将列表、数组之类的集合传递给 python 中的另一个函数时,它会复制它,还是只是一个指针?
8 回答
Python通过 value 传递对对象的引用。
Python 按值传递对对象的引用(如 Java),Python 中的一切都是对象。这听起来很简单,但随后您会注意到某些数据类型似乎表现出按值传递的特征,而另一些数据类型似乎表现得像按引用传递......这是怎么回事?
了解可变和不可变对象很重要。一些对象,如字符串、元组和数字,是不可变的。在函数/方法内部更改它们将创建一个新实例,而函数/方法外部的原始实例不会更改。其他对象,如列表和字典是可变的,这意味着您可以就地更改对象。因此,更改函数/方法内部的对象也会更改外部的原始对象。
问题是,整个参考/价值概念不适合 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
因此,我可以回答您的问题:
它是“按值传递”,但所有值都只是对对象的引用。
这里的答案很有帮助,但我发现需要展示我没有看到的这种细微差别,我已经通过随后的 CL 实验向自己证明了这一点:
- 在函数调用中不能单独更改不可变对象。(到目前为止的答案已经说了很多......)
- 但是,包含在可变对象中的不可变对象可以在方法调用中重新分配。
'num' 在这里没有改变,因为它是一个不可变的 Number 对象[支持我的观点 1。]:
def incr_num(num):
num += 1
num = 0
num
0
incr_num(num)
num
0
'list[0]' 这里也是一个不可变的 Number 对象。
def incr_list(list):
list[0] += 1
list = [0]
list[0]
0
incr_list(list)
list[0]
1
那么,作为不可变的 Number 对象,'list[0]' 是如何改变的(支持我的观点 2.),而上面示例的 Number 对象 'num' 没有? 不可变的 Number 对象“list[0]”包含在可变列表对象“list”中,而第一个示例中的“num”只是一个非包含的 Number 对象(不可变)。
虽然出于善意,但我觉得@Stephen Pape评价最高的答案(引用如下)和其他一些类似的答案并不完全正确(这促使我写下这个答案):
一些对象,如字符串、元组和数字,是不可变的。在函数/方法内部更改它们将创建一个新实例,而函数/方法外部的原始实例不会更改。
我上面的第二个代码实验显示了一个 Number 对象 ('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', ''] '6'、'7'、'8'、'9']
映射到内存地址 28329344 28331264 var1 var2 ab x 之后 a=b a 之后 b=x b 之后 a[0] = '20' [0] = '20' 之后 return ['1','2','3', '4'] ['20', '6', '7', '8', '9']