当前位置:首页 > Python > 正文

Python函数参数传递机制详解(从新手到理解底层原理)

在学习 Python 编程的过程中,很多初学者都会对“函数参数是如何传递的”感到困惑。有时候修改了函数内的参数,外部变量也会跟着变;有时候却不会。这背后其实隐藏着 Python 独特的参数传递机制。本文将用通俗易懂的方式,带你彻底搞懂 Python参数传递 的原理。

一、先看一个“奇怪”的例子

请看下面这段代码:

# 示例1:整数(不可变对象)def change_num(x):    x = 100    print("函数内 x =", x)a = 10change_num(a)print("函数外 a =", a)# 输出:# 函数内 x = 100# 函数外 a = 10

再看另一个例子:

# 示例2:列表(可变对象)def change_list(lst):    lst.append(4)    print("函数内 lst =", lst)my_list = [1, 2, 3]change_list(my_list)print("函数外 my_list =", my_list)# 输出:# 函数内 lst = [1, 2, 3, 4]# 函数外 my_list = [1, 2, 3, 4]

为什么第一个例子中 a 没变,而第二个例子中 my_list 却变了?这就要从 Python 的对象模型说起。

二、Python 中“一切皆对象”

在 Python 中,所有数据都是对象,包括数字、字符串、列表等。每个对象都有两个关键属性:

  • 值(value):对象存储的实际数据。
  • 身份(id):对象在内存中的唯一地址,可通过 id() 函数查看。

更重要的是,Python 将对象分为两类:

  • 不可变对象(Immutable):如 int、float、str、tuple。一旦创建,其值不能被修改。
  • 可变对象(Mutable):如 list、dict、set。创建后可以修改其内容。
Python函数参数传递机制详解(从新手到理解底层原理) Python参数传递 可变对象 不可变对象 引用传递 第1张

三、Python 参数传递的本质:传对象引用

Python 的参数传递既不是“传值”,也不是传统意义上的“传引用”,而是 “传对象引用”(Pass-by-object-reference)

当你调用函数时,Python 会把实参的 对象引用 传递给形参。也就是说,形参和实参指向同一个对象。

但关键在于:如果你在函数内部 重新赋值 形参(如 x = 100),你只是让形参指向了一个新对象,而不会影响原来的实参。但如果你 修改对象本身的内容(如 lst.append()),因为对象是同一个,所以外部也能看到变化。

四、深入理解:不可变 vs 可变

1. 不可变对象(如 int、str)

由于不可变对象不能被修改,任何“修改”操作实际上都会创建一个新对象。因此,函数内部对形参的赋值不会影响外部。

a = 10print(id(a))  # 假设输出 1407...def func(x):    print(id(x))  # 和 a 的 id 相同    x = 20        # 创建新对象,x 指向新地址    print(id(x))  # 新 idfunc(a)print(a)  # 仍然是 10

2. 可变对象(如 list、dict)

可变对象可以在原地修改,因此通过形参调用其方法(如 .append().update())会直接影响原始对象。

my_dict = {'a': 1}print(id(my_dict))def modify(d):    print(id(d))      # 和 my_dict 相同    d['b'] = 2        # 修改原对象    print(id(d))      # id 不变!modify(my_dict)print(my_dict)  # {'a': 1, 'b': 2}

五、如何避免意外修改?

如果你不希望函数修改原始的可变对象,可以在函数内部创建副本:

def safe_change(lst):    new_lst = lst.copy()  # 或 list(lst), lst[:]    new_lst.append(999)    return new_lstoriginal = [1, 2, 3]result = safe_change(original)print(original)  # [1, 2, 3] —— 未被修改print(result)    # [1, 2, 3, 999]

六、总结

- Python 参数传递是 传对象引用

- 对于 不可变对象,函数内重新赋值不会影响外部。

- 对于 可变对象,若在函数内修改其内容,外部会同步变化。

- 理解 引用传递 和对象的可变性,是掌握 Python 编程的关键一步。

掌握这些知识后,你就能自信地处理函数参数,避免常见的“副作用”陷阱。这也是面试中常被问到的 Python参数传递 核心知识点之一。