在Python中,所有参数传递都是"对象引用传递"。这意味着传递给函数的是对象的引用(内存地址),而不是对象本身的副本。然而,根据对象类型(可变或不可变),函数内对参数的操作会产生不同的结果:
当传递不可变对象时,函数内部对参数的修改不会影响原始变量,因为操作会创建新对象:
def modify_number(x):
print("函数内 - 修改前:", x, id(x))
x = x + 10 # 创建新对象
print("函数内 - 修改后:", x, id(x))
num = 5
print("调用前:", num, id(num))
modify_number(num)
print("调用后:", num, id(num)) # 原始值未改变调用前: 5 140719415175744
函数内 - 修改前: 5 140719415175744
函数内 - 修改后: 15 140719415176064
调用后: 5 140719415175744
关键点: 函数内部修改创建了新整数对象,原始变量保持不变。内存地址变化证明创建了新对象。
当传递可变对象时,函数内部对参数的修改会影响原始对象:
def modify_list(lst):
print("函数内 - 修改前:", lst, id(lst))
lst.append(4) # 修改原列表
lst[0] = 99 # 修改原列表
print("函数内 - 修改后:", lst, id(lst))
my_list = [1, 2, 3]
print("调用前:", my_list, id(my_list))
modify_list(my_list)
print("调用后:", my_list, id(my_list)) # 原始列表被修改调用前: [1, 2, 3] 140258147731648
函数内 - 修改前: [1, 2, 3] 140258147731648
函数内 - 修改后: [99, 2, 3, 4] 140258147731648
调用后: [99, 2, 3, 4] 140258147731648
关键点: 函数内部修改影响了原始列表。所有操作使用相同内存地址,证明操作的是同一个对象。
理解重新赋值和就地修改的区别至关重要,这解释了为什么有时可变对象也不会被修改:
def reassign_list(lst):
print("函数内 - 重新赋值前:", lst, id(lst))
lst = [10, 20, 30] # 创建新列表对象
print("函数内 - 重新赋值后:", lst, id(lst))
def modify_list_inplace(lst):
print("函数内 - 修改前:", lst, id(lst))
lst.append(100) # 就地修改原列表
print("函数内 - 修改后:", lst, id(lst))
original_list = [1, 2, 3]
print("=== 重新赋值示例 ===")
print("调用前:", original_list, id(original_list))
reassign_list(original_list)
print("调用后:", original_list, id(original_list)) # 原始列表不变
print("\n=== 就地修改示例 ===")
print("调用前:", original_list, id(original_list))
modify_list_inplace(original_list)
print("调用后:", original_list, id(original_list)) # 原始列表被修改函数内修改会创建新对象,原始对象不变
函数内就地修改会影响原始对象
new_list = old_list.copy()new_dict = old_dict.copy()new_set = old_set.copy()copy.deepcopy()处理嵌套对象def safe_modify(data):
"""处理列表数据但不修改原始列表"""
# 创建副本进行操作
working_copy = data.copy()
working_copy.append("安全修改")
working_copy[0] = 100
return working_copy
original = [1, 2, 3]
result = safe_modify(original)
print("原始列表:", original) # [1, 2, 3]
print("处理结果:", result) # [100, 2, 3, '安全修改']关键点 | 说明 |
|---|---|
传递机制 | 对象引用传递(传递内存地址) |
不可变对象 | 类似值传递效果(函数内修改创建新对象) |
可变对象 | 类似引用传递效果(函数内就地修改影响原对象) |
重新赋值 | 创建新对象,不影响原始对象 |
最佳实践 | 根据需求选择对象类型,需要保护原始数据时使用副本 |
核心原则: Python中一切皆对象,函数参数传递的是对象引用。要改变函数外部的变量,要么使用可变对象并进行就地修改,要么返回新值并重新赋值。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。