python中函数的传参是传引用还是传值呢?
相信很多人从c++转投python时都跟我有一样的困惑。
实际上,python既不是传参也不是传引用。应该称其为传对象引用。
代码永远是最好的讲解,show code!
def inc(n):
print(id(n))
n=n+1
print(id(n))
b=1
print(b)
print(id(b))
inc(b)
print(b)
print(id(b))
>>>
1
8791320941600
8791320941600
2
8791320941632
1
8791320941600
这个栗子说明:传引用这个说法不对!
def kill_weapon(n):
n.append("www.baidu.com")
n.append("tank")
n.append("gun")
b=[]
print(b)
print(id(b))
kill_weapon(b)
print(b)
print(id(b))
>>>
[]
30302792
['www.baidu.com', 'tank', 'gun']
30302792
这个栗子又说明,传值说法也不对。
你这时候可能会觉得,那这样说的通嘛,可变对象传引用,不可变对象传值,那么请你看以下代码
def change_list(m):
print(m)
print(id(m))
if len(m)>3:
m=["马化腾","马云","我"]
for k,v in enumerate(m):
if isinstance(v,list):
m[k]="嘤嘤嘤"
print(m)
print(id(m))
notchange=[1,['a',1,3],[2,1],6]
print(notchange)
print(id(notchange))
change_list(notchange)
print(notchange)
print(id(notchange))
change=[1,[],]
change_list(change)
print(change)
print(id(change))
>>>
[1, ['a', 1, 3], [2, 1], 6]
31616840
[1, ['a', 1, 3], [2, 1], 6]
31616840
['马化腾', '马云', '我']
31402440
[1, ['a', 1, 3], [2, 1], 6]
31616840
[1, []]
31407432
[1, '嘤嘤嘤']
31407432
[1, '嘤嘤嘤']
31407432
正常人看到这里大概就已经蒙了,怎么一个能在函数内修改函数外的list,一个不行呢?
甘霖娘,python的传参机制到底是咋样的?
要明白python的参数传递机制,我们首先要理解python的赋值机制。
举个栗子吧
a=5
b=a
b=7
上面三个语句在c++中的执行大概是这样的。
a=5;//申请一块内存,把这块内存的值赋值为5
b=a;//申请一块内存,把a的值即5读出来赋值给b
b=7;//把这一块内存的值修改为7
//感兴趣的话可以通过指针去看一下,这篇文章主要讲的是python我就不手动写了
而在python中呢
>>> a=5#a指向5这个对象
>>> print(id(a)
8791325005024
>>> b=a#b通过a,同样指向5这个对象
>>> print(id(b)
8791325005024
>>> b=7#b指向7这个对象
>>> print(id(b)
8791325004960
哦吼,是不是感觉有点小懂了?
我们回头看最后一个函数。
第一次调用为什么没有改变值呢?好看的朋友已经发现了,因为,m指向的对象已经从[1,['a',1,3],[2,1],6],变成了["马化腾","马云","我"]了呀,所以给你一百次操作也不会改变[1,['a',1,3],[2,1],6]这个对象的值呀。
第二次调用呢,始终m指向的都是[1,[],]这个对象,所以函数中的修改可以影响到函数外。
以上。