【每天1分钟】PYTHON基础之函数(参数传递处理)
- 值传递 VS 引用传递
值传递(passl-by-value)过程中,被调函数的形式参数作为被调函数的局部变量处理,即在堆栈中开辟了内存空间以存放由主调函数放进来的实参的值,从而成为了实参的一个副本。值传递的特点是被调函数对形式参数的任何操作都是作为局部变量进行,不会影响主调函数的实参变量的值。
引用传递(pass-by-reference)过程中,被调函数的形式参数虽然也作为局部变量在堆栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过堆栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的实参变量。
先说结论:
python不允许程序员选择采用传值还是传引用。Python参数传递采用的肯定是“传对象引用”的方式。这种方式相当于传值和传引用的一种综合。如果函数收到的是一个可变对象(比如字典或者列表)的引用,就能修改对象的原始值--相当于通过“传引用”来传递对象。如果函数收到的是一个不可变对象(比如数字、字符或者元组)的引用,就不能直接修改原始对象--相当于通过“传值’来传递对象。
- 举例
>>> def add1(arg):
print('before add, id(arg):',id(arg))
print('before add, arg:',arg)
arg += 1
print('after add, id(arg):',id(arg))
print('after add, arg:',arg)
return arg
>>> arg = 1
>>> id(arg)
1655005408
>>> add1(arg)
before add, id(arg): 1655005408
before add, arg: 1
after add, id(arg): 1655005440
after add, arg: 2
2
>>> arg
1
>>>
执行 add1 前
执行 add1 后
>>> def alterList(list1):
print('before alterList, id(list1)',id(list1))
print('before alterList, list1[1]',list1[1])
list1[1] += 1
print('after alterList, id(list1)',id(list1))
print('after alterList, list1[1]',list1[1])
return list1
>>> list1 = ["li", 18, "female"]
>>> list1
['li', 18, 'female']
>>> id(list1)
2154237201800
>>> alterList(list1)
before alterList, id(list1) 2154237201800
before alterList, list1[1] 18
after alterList, id(list1) 2154237201800
after alterList, list1[1] 19
['li', 19, 'female']
>>> list1 # 注意 list1[1] 已经从18变成了19
['li', 19, 'female']
>>> id(list1)
2154237201800
>>>
执行 alterList 前
执行 alterList 后