值传递和引用传递
func(arg1,arg2)
在函数中,定义函数的时候写的参数叫形参,调用函数传入的参数叫实参。
值传递的意思是实参传递进去的其实是数据对象的一个副本,并不会对原对象产生影响,引用传递是指穿进去的是参数对象的内存地址,因此期间对参数的操作是会对原对象产生影响的。
就结论而言,python的不可变对象是值传递,可变对象是引用传递。不像C,可以指定是值传递或是引用传递。
python的数据类型
在Python中,万物皆对象。python的数据类型可分为 不可变对象 和 可变对象。
每个对象可以通过id()
来查看标识符,标识符类似于内存地址,相同的标识符指向同一个内存空间。type()
可以查看对象的类型。
- 不可变对象:
int
整形、float
浮点型、str
字符串、tuple
元组 - 可变对象:
list
、set
、dict
对于不可变对象,创建变量时如果值相同,python会分配同一个内存地址。
>>> a = 1
>>> b = 1
>>> c = 2
>>> a is b
True
>>> a is c
False
>>> id(a)
2244378782000
>>> id(b)
2244378782000
而可变对象的每次创建,python都会分配一个内存空间给每个对象。
>>> list_a = [1]
>>> list_b = [1]
>>> id(list_a)
2244381168128
>>> id(list_b)
2244381071168
验证
- 值传递的情况
测试一:
def foo(arg):
arg += 1
print(arg)
return
a = 1
foo(a)
print(a)
# ============输出=============
2
1
测试二:
def foo2(arg):
print('传进来的值的id:%s'%id(arg))
print('-'*30)
arg+=1
print('操作后的值的id:%s'%id(arg))
print('arg的值:',arg)
print('-'*30)
a=1
id(a)
foo2(a)
id(a)
# ===========输出==============
In [10]: a=1
In [11]: id(a)
Out[11]: 1736435632
In [12]: foo2(a)
传入的arg的id: 1736435632
------------------------------
操作后的id:1736435648
arg的值: 2
------------------------------
In [13]: id(a)
Out[13]: 1736435632
- 引用传递的情况
def foo3(arg):
if isinstance(arg, list):
print('传入的arg的id:%s'%id(arg))
arg.append(1)
print('-'*30)
print('操作后的arg的id:%s'%id(arg))
print('-'*30)
if isinstance(arg, set):
print('传入的arg的id:%s'%id(arg))
arg.add(2)
print('-'*30)
print('操作后的arg的id:%s'%id(arg))
print('-'*30)
if isinstance(arg, dict):
print('传入的arg的id:%s'%id(arg))
arg.add(2)
print('-'*30)
print('操作后的arg的id:%s'%id(arg))
print('-'*30)
# =================输出=====================
In [30]: list_b = [1]
In [31]: id(list_b)
Out[31]: 106624040
In [32]: foo3(list_b)
传入的arg的id:106624040
------------------------------
操作后的arg的id:106624040
------------------------------
扩展:
还顺便测试了一下