Python函数值传递与引用传递
定义函数def语句函数名后面的变量叫做函数的形参,调用函数时传入的值是实参;
根据调用函数传入实参类型不同,函数参数的传递方式分为值传递与引用传递;
值传递
实参数据类型是不可变对象(字符串、数字、元组),则函数的传递方式是值传递,本质是将实参的副本传入函数,在函数内部把参数重新赋值,而参数本身不会受到任何影响。
def try_to_change(obj): obj += obj print("形参值为:", obj) a = 'python学习' print("a的值为:", a) # 实参字符串类型 try_to_change(a) print("实参值为:", a) a = (7, 8, 9) print("a的值为:", a) # 实参元组类型 try_to_change(a) print("实参值为:", a) a = 6 print("a的值为:", a) # 实参数字类型 try_to_change(a) print("实参值为:", a) 运行结果: a的值为: python学习 形参值为: python学习python学习 实参值为: python学习 a的值为: (7, 8, 9) 形参值为: (7, 8, 9, 7, 8, 9) 实参值为: (7, 8, 9) a的值为: 6 形参值为: 12 实参值为: 6
引用传递
实参数据类型是可变对象(列表、字典),则函数的传递方式是引用传递,这种传递方式仍是不折不扣的值传递,复制可变对象的引用变量传入函数内,并未复制可变对象本身。但是不管是操作主程序实参值本身,还是操作函数内的形参,都是操作它们相同对象引用变量。
def try_to_change(obj): obj += obj print("形参值为:", obj) a = [1, 2, 3] print("a的值为:", a) # 实参列表类型 try_to_change(a) print("实参值为:", a) 运行结果: a的值为: [1, 2, 3] 形参值为: [1, 2, 3, 1, 2, 3] 实参值为: [1, 2, 3, 1, 2, 3]
为了避免对原始对象数据的影响,比如列表可以通过切片方式得到一个副本。
def try_to_change(obj): obj += obj print("形参值为:", obj) a = [1, 2, 3] print("a的值为:", a) # 复制整个列表的切片,则不会影响原始的列表 try_to_change(a[:]) print("实参值为:", a) 运行结果: a的值为: [1, 2, 3] 形参值为: [1, 2, 3, 1, 2, 3] 实参值为: [1, 2, 3]
由此可见,无论是值传递还是引用传递,我们只需关注函数内部是否会生成新的对象即可。凡是对原对象操作的函数,都会影响传递的实际参数;凡是生成新对象的操作,都不会影响传递的实际参数。