Py学习  »  Python

揭秘Python魔法:当List成为函数参数时,到底发生了什么?

A逍遥之路 • 3 月前 • 122 次点击  

你有没有遇到这样的场景:明明给函数传了一个列表,结果在函数内部做了修改,原列表竟然也“身体力行”地跟着变了?这背后到底藏着怎样的“魔法”?今天,我们就要带你走进 Python 的参数传递世界,探秘 List 作为参数时的奥秘!


💡 1、参数传递的三种基本观念

在深入 List 之前,先回顾一下函数参数的基本传递方式:

  1. 按值传递(Pass by Value) 复制一份实参到形参,互不影响。

  2. 按引用传递(Pass by Reference) 传入变量的引用,函数内外操作同一块内存。

  3. Python式“传对象引用”(Call by Object Reference) 既不是纯“值传递”,也非严谨“引用传递”,而是一种“传对象引用”:形参指向同一个对象,是否修改要看对象类型及操作方式。


🔍 2、List:可变对象 VS 不可变对象

在 Python 中,数据类型大体分为两类:

  • 不可变对象(Immutable):如 intstrtuple。一旦创建,不可修改。

  • 可变对象(Mutable):如 listdict、自定义对象。可以在原地修改。

为什么 List 会“自带穿越”?




    
def func(my_list):
    my_list.append(42)

data= [123]
func(data)
print(data)  # [1, 2, 3, 42]

原因:data 和 my_list 都指向同一块列表内存,当我们调用 append,是就地修改,没有复制。


🔧 3、常见误区·与“重绑定”玩法

def func2(my_list):
    my_list= [100200]      # 给形参重新赋值
    print("内部:"my_list)   # [100, 200]

data= [123]
func2(data)
print("外部:"data)         # [1, 2, 3]
  • 这里的 my_list = [...]  是 重绑定,让形参指向新的列表,不影响原列表。

  • 对列表本身的“编辑”.append().pop()、下标赋值等)会改变原列表;而 重绑定 只是在函数内部更换了形参指向。


🚀 4、最佳实践:保护你的列表!

为了避免意外修改或提升代码可读性,我们常用下面几招:

  1. 传入副本

    func(data.copy())
  2. 使用不可变数据结构

  • 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,AI,自动化办公提效,副业发展等感兴趣的伙伴们,扫码添加逍遥,限免交流群

    备注【成长交流】

    图片

    Python社区是高质量的Python/Django开发社区
    本文地址:http://www.python88.com/topic/183489