2021-08-22 13:33:25
Python中函数的参数传递本质是赋值传递(pass by assignment),也可理解为对象引用传递,其核心是传递对象的引用而非对象本身。具体分析如下:
赋值传递的本质Python中所有变量本质上都是对象的引用(类似指针,但无需显式操作内存地址)。当调用函数时,参数传递的行为类似于将实参的引用赋值给形参。例如:
def fun(param): param = 1 # 形参param重新指向新对象1,不影响实参aa = 10fun(a)print(a) # 输出10此时param = a等价于将a的引用赋值给param,但后续param = 1会改变param的指向,而a仍指向原对象10。
不可变对象与赋值传递若参数为不可变对象(如整数、字符串、元组),函数内对形参的修改会创建新对象,实参不受影响。例如:
def modify_param(param): param += 1 # 创建新对象11,param指向新对象x = 10modify_param(x)print(x) # 输出10因整数不可变,param += 1不会修改原对象,而是生成新对象11,x仍指向10。
可变对象与赋值传递若参数为可变对象(如列表、字典),函数内对形参的修改会直接影响实参,因为操作的是同一对象。例如:
def modify_list(param): param[1] = 0 # 修改原对象的元素lst = [1, 2, 3]modify_list(lst)print(lst) # 输出[1, 0, 3]此时param和lst指向同一列表对象,修改param[1]等价于直接修改lst。
与C语言参数传递的对比
C的值传递:传递对象副本,函数内修改不影响实参。
C的地址传递:传递内存地址,函数内通过指针修改原对象。
C的引用传递:通过别名直接操作原对象(类似Python可变对象的传递行为)。Python的赋值传递更灵活:无论对象是否可变,传递的始终是引用,但修改行为取决于对象类型——不可变对象需创建新对象,可变对象可直接修改。
关键注意事项
避免混淆引用与对象本身:Python中“传递引用”不意味着传递内存地址,而是传递对象的绑定关系。
可变对象的副作用:函数内修改可变对象参数会影响外部变量,需谨慎操作。
防御性编程:若需避免修改可变对象,可在函数内创建副本(如param = list(param))。
总结:Python的参数传递是赋值传递,即传递对象引用的副本。对于不可变对象,函数内修改会生成新对象;对于可变对象,修改会直接影响原对象。理解这一点需结合Python的变量模型(对象+引用)和对象可变性,而非简单类比C的传递方式。