Files
PythonLearn/01_python基础/1_13_函数进阶

第 1-13 课:函数进阶

一、本课目标

完成本课后,你将能够:

  1. 使用 return 一次返回多个结果;
  2. 使用提前返回减少不必要的嵌套;
  3. 使用 *args 接收任意数量的位置参数;
  4. 使用 **kwargs 接收任意数量的关键字参数;
  5. 使用 *** 在调用函数时解包数据;
  6. 根据不同任务选择普通参数、*args**kwargs
  7. 继续练习让函数保持清晰、职责单一。

二、前置知识

学习本课前,需要理解:

  • 如何使用 def 定义函数;
  • 如何调用函数;
  • 位置参数、关键字参数和默认参数;
  • print()return 的区别;
  • 列表、元组和字典;
  • 条件判断和循环。

三、一次返回多个结果

一个函数可以在 return 后面写多个值:

def get_agent_summary(agent):
    return agent["name"], len(agent.get("tools", []))


agent_name, tool_count = get_agent_summary({
    "name": "代码助手",
    "tools": ["搜索", "终端"],
})

print(agent_name)
print(tool_count)

Python 实际上会先把多个返回值组合成一个元组,再把元组解包给多个变量。

也可以只用一个变量接收:

summary = get_agent_summary({"name": "聊天助手", "tools": []})
print(summary)
print(type(summary))

此时 summary 是元组,例如 ("聊天助手", 0)

四、提前返回

return 不只负责返回结果,还会立即结束当前函数。

def get_agent_status(agent):
    if not agent.get("enabled", False):
        return "停用"

    return "启用"

如果 Agent 没有启用,函数执行第一个 return 后就结束,不会继续执行下面的代码。

这种写法称为提前返回Early Return。它适合先处理无效数据或特殊情况避免出现太多层缩进。

五、使用 *args 接收多个位置参数

有时无法提前确定调用者会传入几个位置参数,这时可以使用 *args

def count_tools(*tools):
    return len(tools)


print(count_tools("搜索"))
print(count_tools("搜索", "终端", "计算器"))

这里的 args 是 arguments 的缩写,表示“多个参数”。

需要注意:

  • 参数名前面的 * 才是关键;
  • args 是约定俗成的名称,也可以换成其他名称;
  • 函数内部的 tools 是一个元组;
  • 即使没有传入任何工具,tools 也是空元组。
def show_tools(*tools):
    print(tools)
    print(type(tools))

六、普通参数和 *args 一起使用

普通参数可以写在 *args 前面:

def build_tool_message(agent_name, *tools):
    return f"{agent_name} 拥有 {len(tools)} 个工具"


message = build_tool_message("代码助手", "搜索", "终端")
print(message)

调用时,第一个位置参数交给 agent_name,剩余位置参数都被收集到 tools 元组中。

七、使用 **kwargs 接收多个关键字参数

如果无法提前确定调用者会传入哪些关键字参数,可以使用 **kwargs

def build_agent_config(**config):
    return config


agent_config = build_agent_config(
    name="代码助手",
    model="gpt-5",
    enabled=True,
)

print(agent_config)

kwargs 是 keyword arguments 的缩写,中文可理解为“多个关键字参数”。

函数内部的 config 是字典:

{
    "name": "代码助手",
    "model": "gpt-5",
    "enabled": True,
}

同样,参数名前面的两个星号 ** 才是关键,kwargs 只是常见命名。

八、普通参数和 **kwargs 一起使用

def create_agent(name, **settings):
    return {
        "name": name,
        "settings": settings,
    }


agent = create_agent("代码助手", model="gpt-5", enabled=True)
print(agent)

name 接收普通参数,其他关键字参数被收集到 settings 字典中。

九、调用函数时使用 * 解包列表或元组

星号也可以出现在函数调用中。此时它表示把列表或元组中的元素依次作为位置参数传入。

def add_three_numbers(first, second, third):
    return first + second + third


numbers = [10, 20, 30]
total = add_three_numbers(*numbers)
print(total)

上面的调用相当于:

total = add_three_numbers(10, 20, 30)

元素数量必须与函数所需的位置参数数量匹配,否则会产生 TypeError

十、调用函数时使用 ** 解包字典

两个星号可以把字典解包成关键字参数:

def describe_agent(name, model):
    return f"{name} 使用 {model}"


agent_data = {
    "name": "代码助手",
    "model": "gpt-5",
}

description = describe_agent(**agent_data)
print(description)

上面的调用相当于:

description = describe_agent(name="代码助手", model="gpt-5")

字典的键必须与函数参数名一致。

十一、如何选择参数形式

使用普通参数

参数数量固定、含义明确时,优先使用普通参数:

def get_total(first_number, second_number):
    return first_number + second_number

使用 *args

需要接收数量不固定的同类位置参数时使用:

def count_tools(*tools):
    return len(tools)

使用 **kwargs

需要接收数量或名称不固定的配置项时使用:

def build_config(**config):
    return config

不要为了显得代码高级而强行使用 *args**kwargs。参数固定时,普通参数通常更清楚。

十二、完整示例

本课示例文件为:

01_python基础/1_13_函数进阶/advanced_functions.py

示例会依次演示:

  1. 返回多个结果;
  2. 提前返回;
  3. 使用 *args
  4. 使用 **kwargs
  5. 解包列表和字典后调用函数。

十三、运行方法

在项目根目录执行:

python .\01_python基础\1_13_函数进阶\advanced_functions.py

运行练习:

python .\01_python基础\1_13_函数进阶\practice.py

十四、示例运行结果

一、返回多个结果
Agent 名称:代码助手
工具数量2
==============================
二、提前返回
启用
停用
==============================
三、任意数量的位置参数
工具数量3
==============================
四、任意数量的关键字参数
{'name': '代码助手', 'model': 'gpt-5', 'enabled': True}
==============================
五、调用时解包数据
数字总和60
代码助手 使用 gpt-5

字典的显示格式可能因环境而略有差异,但键和值应当一致。

十五、关键代码解析

def count_tools(*tools):
    return len(tools)

执行顺序如下:

  1. 调用者传入零个或多个位置参数;
  2. * 把这些参数收集到 tools
  3. tools 在函数内部是元组;
  4. len() 统计元组中的元素数量;
  5. return 把数量交给调用者。
def build_agent_config(**config):
    return config

执行顺序如下:

  1. 调用者传入零个或多个关键字参数;
  2. ** 把参数名称和值收集到 config
  3. config 在函数内部是字典;
  4. 函数把字典返回给调用者。

十六、常见错误

16.1 混淆 *args**kwargs

  • *args 收集位置参数,函数内部得到元组;
  • **kwargs 收集关键字参数,函数内部得到字典。

16.2 忘记星号

argskwargs 本身只是普通名称。真正产生收集效果的是 ***

16.3 解包后的参数数量不匹配

如果函数需要三个参数,列表却只有两个元素,会产生 TypeError,表示调用时提供的参数数量不正确。

16.4 字典键与参数名不一致

使用 **dictionary 调用函数时,字典键必须能对应函数参数名。

16.5 在 return 后继续编写必须执行的代码

函数执行到 return 就会结束,写在同一执行路径后面的代码不会运行。

16.6 所有函数都使用可变参数

固定且明确的数据应继续使用普通参数。过度使用可变参数会降低可读性。

十七、课堂练习

打开:

01_python基础/1_13_函数进阶/practice.py

练习题已经明确提供输入数据、实现步骤、返回要求和预期结果。请先独立完成,再进行验证。

十八、本课小结

  1. return value1, value2 可以返回多个结果;
  2. 多个返回值实际会组合成元组;
  3. 提前返回可以尽早结束函数;
  4. *args 收集位置参数并形成元组;
  5. **kwargs 收集关键字参数并形成字典;
  6. 调用函数时,* 可以解包列表或元组;
  7. 调用函数时,** 可以解包字典;
  8. 参数固定时应优先使用普通参数。

十九、验收标准

  • 能正确接收函数的多个返回值;
  • 能解释 return 为什么会结束函数;
  • 能使用 *args 接收不同数量的位置参数;
  • 能说明 *args 在函数内部是元组;
  • 能使用 **kwargs 接收关键字参数;
  • 能说明 **kwargs 在函数内部是字典;
  • 能使用 * 解包列表或元组后调用函数;
  • 能使用 ** 解包字典后调用函数;
  • 示例程序和练习程序可以正常运行。