Python函数定义与调用:参数传递及返回值基础教程

小岛来信
小岛来信
发布时间:2026-11-01| 9人浏览过
原创

本教程系统讲解Python函数定义与调用的基础语法与核心底层逻辑,深入剖析位置参数、默认参数、可变参数以及对象引用传递机制,帮助读者掌握优雅可靠的函数设计方法。

编写高质量 Python 程序的关键之一,在于将复杂业务拆解为职责明确、便于复用的函数。函数是组织好的、可重复利用的代码块,负责实现特定的单一功能。本文系统梳理从函数声明关键字 def、函数调用机制,到实参与形参匹配、底层引用传递本质,以及返回值控制的完整知识链条,配合流程示意图与标准示例,帮助读者建立扎实可靠的函数编程基础。

一、函数基本结构:从定义到调用

在 Python 中,声明函数使用 def(define 的简写)关键字,后跟函数名称、圆括号 () 以及冒号 :,随后通过严格缩进的代码块构成函数体。函数定义完成后并不会自动执行,只有当程序显式使用“函数名+圆括号”发起调用时,解释器才会跳转并执行其内部指令。

# 示例:基础函数的声明与调用
def calculate_rectangle_area(width, height):
    """计算矩形面积并返回结果。"""
    area = width * height
    return area

# 调用函数并接收返回值
result = calculate_rectangle_area(12, 8)
print("矩形面积为:", result)  # 输出:矩形面积为: 96

一次完整的函数执行通常经历四个连续阶段:首先是函数声明解析,解释器在内存中创建函数对象;其次是调用指令触发,计算传入实参并建立独立调用栈帧;随后在独立作用域内执行语句;最后通过 return 指令回传数据并销毁栈帧。

Python函数定义与调用:参数传递及返回值基础教程
图 1:Python 函数定义与调用执行流架构图

二、形参与实参:五类参数传递规则

在函数声明中出现的变量称为形参(Parameter),它属于局部占位符;而在调用函数时传入的真实数据或表达式结果称为实参(Argument)。Python 提供了极具弹性的参数传递语法,但必须遵循固定的语法先后次序。

1. 位置参数与关键字参数

最标准的传参方式是位置参数,实参与形参按照从左到右的位置次序一对一绑定。若希望代码具备更强自解释性或希望打破传参顺序,可显式指定形参名称,即关键字参数。

def create_user_profile(username, role, status):
    return f"用户:{username} | 角色:{role} | 状态:{status}"

# 按照位置传递
print(create_user_profile("Alice", "Admin", "Active"))

# 使用关键字参数指定,顺序可调换
print(create_user_profile(status="Active", username="Bob", role="Editor"))

2. 默认参数及致命陷阱

可以在函数定义时为形参提供默认初值。调用方如果未传入该参数,解释器会自动代入默认值。所有默认参数必须声明在无默认值的位置参数之后,否则会直接引发 SyntaxError: non-default argument follows default argument。

避坑重点:切勿使用可变对象(如列表、字典)作为默认参数!
Python 函数的默认参数在模块加载时只会被求值并创建一次。若默认值为列表,每次使用该默认值的调用都会共享同一个列表对象,导致数据互相污染。正确的做法是将默认值设为 None,并在函数内部按需初始化。
# 错误示范:多个调用方共享同一个 default 列表
def bad_append(item, target_list=[]):
    target_list.append(item)
    return target_list

# 正确做法:使用 None 作为哨兵值
def safe_append(item, target_list=None):
    if target_list is None:
        target_list = []
    target_list.append(item)
    return target_list

3. 可变参数:*args 与 **kwargs

当预先无法确定传入参数数量时,可以使用星号语法:单个星号 *args 将多余的位置参数收集为一个元组(Tuple);双星号 **kwargs 将多余的关键字参数收集为一个字典(Dictionary)。

def universal_logger(event_type, *args, **kwargs):
    print(f"[事件类型] {event_type}")
    print(f"[位置数据] {args}")       # 元组形式
    print(f"[键值属性] {kwargs}")     # 字典形式

universal_logger("LOGIN", "192.168.1.1", "Firefox", user_id=1001, success=True)
Python函数定义与调用:参数传递及返回值基础教程
图 2:Python 五类形参声明规范与解析链路

三、底层剖析:Python参数传递的本质是“对象引用传递”

许多初学者经常困惑:Python 到底是“值传递”还是“引用传递”?官方定义为“对象引用传递”(Pass-by-object-reference)或“赋值传递”(Pass-by-assignment)。其实质是:函数调用时,形参和实参均成为同一个内存对象的“标签(引用)”。函数内部对参数的操作是否会影响外部变量,完全取决于传入对象的可变性(Mutability):

  • 不可变对象(Immutable:int、float、str、tuple):在函数内部尝试修改该变量时(例如 num += 1),实际上是创建了一个全新的对象并将形参标签重新指向新对象。外部变量依然指向旧对象,因此外部值保持不变。
  • 可变对象(Mutable:list、dict、set):形参和实参共享同一份堆内存数据。若在函数内部使用原位修改方法(如 list.append() 或 dict[key] = val),则外部实参所观察到的数据同步发生改变。若形参执行整体赋值(如 lst = [1, 2]),则同样仅仅是局部重绑定,不影响外部。
Python函数定义与调用:参数传递及返回值基础教程
图 3:Python 参数传递的本质——对象引用传递在不可变与可变对象中的内存表现

四、返回值机制:从单一数据到解包赋值

函数通过 return 语句向外部调用者传递处理结果,并同时终止函数的执行流程。如果在函数体内未编写 return,或者写了不带任何表达式的 return,Python 会隐式返回 None。

1. 返回多个值的本质:元组封装

许多初学者认为 Python 支持“同时返回多个独立变量”,例如 return x, y, z。事实上,Python 解释器在底层自动将逗号分隔的多个对象封装(Pack)成了一个单一体——元组(Tuple)。调用方接收时,再通过序列解包(Unpacking)将其对应赋值给多个局部变量。

def get_coordinate_stat(points):
    min_x = min(p[0] for p in points)
    max_x = max(p[0] for p in points)
    center_x = (min_x + max_x) / 2
    # 语法表面上返回了三个值,底层等价于返回一个元组 (min_x, max_x, center_x)
    return min_x, max_x, center_x

point_list = [(2, 3), (8, 12), (5, 9)]

# 方式 1:利用序列解包分别赋值
low, high, mid = get_coordinate_stat(point_list)
print(f"下界:{low}, 上界:{high}, 中心:{mid}")

# 方式 2:用单一变量整体接收(得到元组)
stat_tuple = get_coordinate_stat(point_list)
print(f"整体元组: {stat_tuple}, 类型: {type(stat_tuple)}")

2. 卫语句(Guard Clauses)与提前返回

编写高质量业务函数时,推荐采用“卫语句”提早退出。当遇到不满足业务前置条件(如输入为空、格式不合法)时,立即 return 退出,避免深层 if-else 嵌套带来的可读性劣化。

# 推荐写法:利用卫语句尽早返回,降低嵌套层级
def process_order(order_id, user_status, balance):
    if user_status != "active":
        return False, "用户账户已被冻结"
    if balance <= 0:
        return False, "账户余额不足"

    # 核心业务逻辑直接平铺展开
    order_token = f"ORD_{order_id}_VERIFIED"
    return True, order_token

五、全景总结与生产级规范

为了编写出健壮、易维护的工程级 Python 函数,建议将参数定义、类型标注(Type Hints)、文档注释(Docstring)与防御式编程原则结合使用:

设计维度 标准做法 常见反模式
默认参数 使用 None 或不可变字面量,内部动态初始化 直接使用 def fn(data=[]),引发状态残留
副作用控制 对可变容器入参优先读取或使用 .copy() 产生副本 无意间原位修改入参列表/字典,导致上游排查困难
返回一致性 各分支返回统一数据结构或明确标记的元组 部分分支返回数字,部分分支返回 False,增加调用复杂度
类型提示 显式标注 def fn(a: int) -> bool: 辅助 IDE 检查 完全缺乏类型提示与 Docstring 文档
Python函数定义与调用:参数传递及返回值基础教程
图 4:Python 函数设计四大核心要素与最佳工程实践

综上所述,函数在 Python 编程中兼具“逻辑抽象单元”与“作用域隔离容器”的双重角色。通过严格遵循形参次序、深入理解对象引用传递、杜绝可变默认参数并熟练运用卫语句,开发者能够编写出模块清晰、稳定且易于维护的高标准 Python 程序。

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。