Python中的函数参数传递机制:按共享传参(Call by Sharing)
字数 783 2025-11-24 19:37:59
Python中的函数参数传递机制:按共享传参(Call by Sharing)
在Python中,函数参数传递机制常被称为"按共享传参"(Call by Sharing)。这意味着函数接收的是实参引用的副本,而不是值的副本。理解这一机制对避免常见的编程错误至关重要。
1. 核心概念:变量是对象的引用
在Python中,变量本质上是对象的引用(或标签),而不是存储数据的容器。例如:
a = 10 # a引用整数对象10
b = a # b引用同一个整数对象10
此时,a和b都指向内存中的同一个对象。
2. 函数调用时的参数传递过程
当调用函数时,实参的引用会被复制给形参。形参成为实参所引用的对象的新引用:
def func(x):
print(id(x)) # 输出x所引用对象的内存地址
a = 10
print(id(a)) # 输出a的内存地址,与func内的x相同
func(a)
这里,x和a都引用同一个整数对象10。
3. 不可变对象参数的行为
对于不可变对象(如整数、字符串、元组),函数内对形参的重新赋值不会影响实参:
def increment(x):
x = x + 1 # 创建新对象,x引用新对象
print("函数内x的值:", x)
a = 10
increment(a) # 输出:函数内x的值: 11
print("函数外a的值:", a) # 输出:函数外a的值: 10
因为整数是不可变的,x + 1会创建一个新对象,x转而引用新对象,而a仍然引用原对象。
4. 可变对象参数的行为
对于可变对象(如列表、字典),函数内修改形参所引用的对象会影响实参:
def append_item(lst):
lst.append(4) # 修改引用对象,不改变引用本身
print("函数内lst:", lst)
my_list = [1, 2, 3]
append_item(my_list) # 输出:函数内lst: [1, 2, 3, 4]
print("函数外my_list:", my_list) # 输出:函数外my_list: [1, 2, 3, 4]
因为lst和my_list引用同一个列表对象,通过任一引用修改对象,变化对两者都可见。
5. 重新绑定与修改对象的区别
关键区别在于操作类型:
- 重新绑定:为形参分配新对象(如
x = x + 1),不影响实参 - 修改对象:通过形参修改引用对象的内容(如
lst.append(4)),影响实参
6. 默认参数的特殊情况
默认参数在函数定义时求值一次,可能导致意外行为:
def add_item(item, lst=[]):
lst.append(item)
return lst
print(add_item(1)) # 输出:[1]
print(add_item(2)) # 输出:[1, 2](非预期结果)
解决方案:使用不可变对象作为默认值,在函数内创建新对象:
def add_item(item, lst=None):
if lst is None:
lst = []
lst.append(item)
return lst
7. 实际应用建议
- 明确区分操作意图:是修改对象还是创建新对象
- 对于可变参数,若需避免副作用,可先创建副本:
def safe_func(lst): new_lst = lst.copy() # 创建副本 # 操作new_lst,不影响原lst - 使用类型注解明确参数预期行为
理解按共享传参机制有助于编写更可预测的代码,特别是在处理可变对象时能避免常见的陷阱。