你有没有遇到这样的场景:明明给函数传了一个列表,结果在函数内部做了修改,原列表竟然也“身体力行”地跟着变了?这背后到底藏着怎样的“魔法”?今天,我们就要带你走进 Python 的参数传递世界,探秘 List 作为参数时的奥秘!
1、参数传递的三种基本观念
在深入 List 之前,先回顾一下函数参数的基本传递方式:
按值传递(Pass by Value) 复制一份实参到形参,互不影响。
按引用传递(Pass by Reference) 传入变量的引用,函数内外操作同一块内存。
Python式“传对象引用”(Call by Object Reference) 既不是纯“值传递”,也非严谨“引用传递”,而是一种“传对象引用”:形参指向同一个对象,是否修改要看对象类型及操作方式。
2、List:可变对象 VS 不可变对象
在 Python 中,数据类型大体分为两类:
不可变对象(Immutable):如 int、str、tuple。一旦创建,不可修改。
可变对象(Mutable):如 list、dict、自定义对象。可以在原地修改。
为什么 List 会“自带穿越”?
def func(my_list):
my_list.append(42)
data= [1, 2, 3]
func(data)
print(data) # [1, 2, 3, 42]
原因:data 和 my_list 都指向同一块列表内存,当我们调用 append,是就地修改,没有复制。
3、常见误区·与“重绑定”玩法
def func2(my_list):
my_list= [100, 200] # 给形参重新赋值
print("内部:", my_list) # [100, 200]
data= [1, 2, 3]
func2(data)
print("外部:", data) # [1, 2, 3]
这里的 my_list = [...] 是 重绑定,让形参指向新的列表,不影响原列表。
对列表本身的“编辑”(.append()、.pop()、下标赋值等)会改变原列表;而 重绑定 只是在函数内部更换了形参指向。
4、最佳实践:保护你的列表!
为了避免意外修改或提升代码可读性,我们常用下面几招:
传入副本
func(data.copy())
使用不可变数据结构
tuple(data),或 Python 3.9+ 的 collections.abc.Sequence。
明确文档与注释
在函数签名和 docstring 中注明:“会修改输入列表” 或 “不会修改输入列表”。
5、实际案例:配置管理 vs 数据清洗
配置管理:有时我们就需要函数修改原列表,比如添加日志、筛选条件等。
数据清洗:常常要保留原始数据,生成干净副本,避免污染。
def clean_data(raw_list):
cleaned= [x.strip() forxinraw_listifx]
return cleaned
origin= [" a ", "", "b"]
new=clean_data(origin)
# origin 不变,new 是干净版本
小结
Python 传参数:引用对象的指针传递,形参指向同一对象。
可变 vs 不可变:可变对象在函数内“同步”变化;重绑定不会影响外部。
防护措施:有意修改可直接操作;若要“只读”,请复制或使用不可变容器。
试试看在你的项目中,哪些函数传入了列表却“不小心”改动了原数据?马上用上面的方法,给代码来个“护甲升级”吧!如果你有更多妙招或疑问,欢迎评论区交流,让我们一起进阶 Python高手!
更多相关技术内容咨询欢迎前往并持续关注好学星城论坛了解详情。
想高效系统的学习Python编程语言,推荐大家关注一个微信公众号:Python编程学习圈。每天分享行业资讯、技术干货供大家阅读,关注即可免费领取整套Python入门到进阶的学习资料以及教程,感兴趣的小伙伴赶紧行动起来吧。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!