认识到精通函数

🐍 PYTHON 零基础入门系列 · 图解版

深入理解 Python 函数

配图说明 · 逐行代码解析 · 从零开始彻底搞懂函数每一个细节

📚 10 大知识点🖼 4 张配图💻 15+ 代码示例🧩 4 道自测题

[① 什么是函数](#① 什么是函数)[② 函数结构](#② 函数结构)[③ 执行流程](#③ 执行流程)[④ 参数类型](#④ 参数类型)[⑤ return用法](#⑤ return用法)[⑥ 作用域](#⑥ 作用域)[⑦ 综合实战](#⑦ 综合实战)[⑧ 为什么用函数](#⑧ 为什么用函数)[⑨ Lambda](#⑨ Lambda)[⑩ 常见错误](#⑩ 常见错误)

1

什么是函数?--- 用一个生活比喻彻底理解

🍳 生活比喻 · 咖啡机模型

想象一台全自动咖啡机

你只需要 投入咖啡豆 + 水(输入/参数) ,按下按钮(调用),

机器内部自动研磨、加热、萃取(函数体运行),

最终出来一杯咖啡(输出/返回值)。

完全不需要知道 机器内部怎么工作------只要会"使用"它。

函数就是这台咖啡机! 封装好的、可重复使用的一段代码。

📌**图解说明:**左边的咖啡豆和水 = 函数的输入参数; 中间机器内部齿轮 = 函数体执行逻辑; 右边咖啡杯 = 函数的返回值(return)

📌 人话版定义

函数是一段被命名的代码块,专门完成某项具体任务。定义一次,随时随地调用,避免重复写相同的代码。就像你存了一个手机联系人,以后直接点名字打电话,不需要每次都重新输电话号码。

2

函数的结构解剖--- 逐行、逐部分读懂每个组成

📌**图解说明:**图中用不同颜色高亮了函数的每一个组成部分,箭头标注了每部分的名称和作用

🔬 逐部分解析对照表

部分 代码示例 作用说明 类比
def 关键字 def 告诉 Python "我要开始定义一个函数了",就像写信开头要写"亲爱的..." 📢 宣告词
函数名 greet 函数的名字,自己取,见名知意。之后调用时就用这个名字。命名规则:小写+下划线 🏷 名字
参数列表 (name, times=1) 括号内写参数,相当于函数的"输入接口"。可以有多个,可以有默认值 📥 输入接口
冒号 : : 固定语法,必须写,告诉 Python 函数体要开始了 🚪 开始标记
函数体 (缩进4格) 真正干活的代码,必须缩进4个空格(或1个Tab),Python 靠缩进判断属于哪个函数 ⚙️ 内部机器
return return message 把结果"返回"给调用者。函数执行到这里就停止,把值交出去。没有return则返回 None 📤 输出接口

function_anatomy.py --- 完整注释版

复制代码
#  ↓ 关键字   ↓ 函数名    ↓ 参数1  ↓ 参数2(有默认值)
def        greet     (name,    times=1):
    # ↑ 冒号不能少!
    # ↓ 函数体:缩进4格,这里才是真正干活的代码
    message = f"你好,{name}!" * times
    return message
    # ↑ return 把结果送出去,函数在这里结束

# ── 调用函数 ──
result = greet("小明", 2)
# result = "你好,小明!你好,小明!"
print(result)

3

函数是怎么运行的?--- 四步执行流程图解

📌**图解说明:**函数执行是一个"去而复返"的过程 ------ 调用时跳进去,执行完再跳回来,把结果带回

1

📝 定义

用 def 写好函数。此时代码不运行,只是把函数"存"进内存

2

📞 调用

写函数名加括号,传入实际参数,Python 就会"去执行"这个函数

3

⚙️ 执行

Python 跳进函数体,把参数赋值,逐行运行函数内的代码

4

🔙 返回

遇到 return(或到函数末尾),带着结果跳回调用处,继续往下执行

execution_flow.py --- 追踪执行顺序

复制代码
# ── 步骤 1:定义(只是"登记",不执行)──
def add(a, b):
    print(f"正在计算:{a} + {b}")   # 步骤3:跳进来执行第1行
    result = a + b               # 步骤3:执行第2行
    return result                 # 步骤4:return,带着结果回去

print("调用之前")               # 先执行这行
x = add(3, 5)                  # 步骤2:调用,跳进 add 函数
print(f"结果是:{x}")          # 步骤4结束后,继续在这里
print("调用之后")

# 输出顺序:
# 调用之前
# 正在计算:3 + 5
# 结果是:8
# 调用之后

💡 关键理解: 定义函数时代码不执行,必须"调用"它才会运行。 就像咖啡机插好电不会出咖啡,按下按钮才会运行。

4

参数的五种写法--- 从最简单到最灵活

① 无参数

函数不需要任何输入,直接执行固定任务

def say_hello():

② 必填参数(位置参数)

调用时必须按顺序传,缺一不可

def add(a, b):

③ 默认参数

有默认值,调用时可省略,也可传新值覆盖

def greet(name, times=1):

④ *args(可变位置)

接收任意数量参数,打包成元组

def sum_all(*numbers):

⑤ **kwargs(可变关键字)

接收任意"名=值"参数,打包成字典

def profile(**info):

param_types.py --- 五种参数完整演示

复制代码
# ① 无参数 —— 最简单
def say_hello():
    print("你好!")

say_hello()        # 调用时括号里什么都不写
# 输出:你好!

# ─────────────────────────────────────────
# ② 必填参数 —— 顺序不能乱
def add(a, b):
    return a + b

print(add(3, 5))    # ✅ 输出:8
# add(3)          # ❌ 报错:缺少参数 b

# ─────────────────────────────────────────
# ③ 默认参数 —— 可传可不传
def make_coffee(size="中杯", sugar=1):
    print(f"制作:{size},加糖 {sugar} 块")

make_coffee()                   # 中杯,加糖 1 块
make_coffee("大杯")              # 大杯,加糖 1 块
make_coffee("大杯", 3)          # 大杯,加糖 3 块
make_coffee(sugar=0)          # 关键字传参,中杯,无糖

# ─────────────────────────────────────────
# ④ *args —— 传多少个都行
def sum_all(*numbers):
    # numbers 是一个元组,如 (1, 2, 3)
    return sum(numbers)

print(sum_all(1, 2, 3))           # 6
print(sum_all(10, 20, 30, 40))     # 100

# ─────────────────────────────────────────
# ⑤ **kwargs —— 传任意"名=值"
def create_profile(**info):
    # info 是一个字典,如 {'name':'黎俊杰', 'age':20}
    for k, v in info.items():
        print(f"  {k}: {v}")

create_profile(name="黎俊杰", age=20, major="数据科学")
# 输出:
#   name: 黎俊杰
#   age: 20
#   major: 数据科学

5

return 的各种用法--- 函数的"出口"

return_usage.py --- 四种 return 情况

复制代码
# ── 情况 1:返回单个值(最常见)──
def square(x):
    return x ** 2          # x 的平方

r = square(5)
print(r)                  # 输出:25

# ── 情况 2:返回多个值(Python 会打包成元组)──
def min_max(lst):
    return min(lst), max(lst)   # 同时返回最小值和最大值

lo, hi = min_max([3, 1, 9, 4])
print(f"最小:{lo},最大:{hi}")  # 最小:1,最大:9

# ── 情况 3:没有 return(返回 None)──
def show_info(msg):
    print(msg)              # 只打印,没有 return

result = show_info("Hi")
print(result)             # 输出:None(空值)

# ── 情况 4:提前退出(条件检查)──
def divide(a, b):
    if b == 0:
        print("错误:除数不能为0!")
        return               # 提前结束,避免程序崩溃
    return a / b

print(divide(10, 2))      # 5.0
print(divide(10, 0))      # 错误:除数不能为0!

📋 return 使用要点总结

情况 语法 调用方得到什么
✅ 返回单值 return x 变量 x 的值
✅ 返回多值 return a, b 元组 (a, b),可以解包
⚪ 无 return 函数末尾没有return None(空值)
🔴 提前退出 return(不带值) None,函数立即结束

6

变量的"生命范围"--- 局部变量 vs 全局变量

📌**图解说明:**全局变量像客厅的电视,整个家(整个程序)都能看到; 局部变量像卧室里的私人物品,只有函数内部能使用,外面无法访问

🏠 房间比喻

全局变量 = 客厅里的电视:全家人(整个程序)都能看。

局部变量 = 你卧室里的私人日记:只有你自己(函数内部)才能翻,出了房间就没了。

函数结束,局部变量就自动消失,就像你关上卧室门,外面的人根本不知道里面有什么。

scope.py --- 作用域完整演示

复制代码
score = 100          # 全局变量:整个文件的函数都能访问它

def show_score():
    print(score)       # ✅ 函数内可以"读"全局变量

def calculate():
    bonus = 20        # 局部变量:只在 calculate 函数内存在
    print(score + bonus)   # ✅ 可以同时用全局+局部变量
    # 函数结束,bonus 就消失了

def modify_score():
    global score     # ⚠️ 要修改全局变量,必须先声明 global
    score += 10

show_score()       # 100
calculate()        # 120
modify_score()
show_score()       # 110(被修改了)

# ❌ 以下会报错:局部变量在函数外不存在
# print(bonus)  →  NameError: name 'bonus' is not defined

7

综合实战--- 用函数开发"学生成绩管理系统"

💡 **目标:**把成绩管理系统拆解成多个小函数,每个函数只负责一件事, 代码清晰、可复用、方便修改。这就是"函数式编程思维"。

🗂 函数拆解设计

函数名 输入 输出 职责
get_average(scores) 成绩列表 浮点数平均分 计算平均分
get_grade(avg) 平均分数值 等级字符串 评定等级
print_report(student) 学生字典 无(只打印) 打印单人报告
print_class_report(list) 学生列表 打印全班报告

student_manager.py --- 完整注释版

复制代码
# =====================================================
# 学生成绩管理系统 — 数据2501班
# =====================================================

# 数据:学生列表,每个学生是一个字典
students = [
    {"name": "黎俊杰", "scores": [90, 85, 92]},
    {"name": "李天宇", "scores": [78, 88, 76]},
    {"name": "刘文财", "scores": [95, 92, 98]},
    {"name": "陈扬",   "scores": [72, 68, 80]},
    {"name": "徐嘉豪", "scores": [88, 91, 87]},
]

# ── 函数① :计算平均分 ──────────────────────────────
def get_average(scores):
    # 接收分数列表,返回浮点数平均分
    return sum(scores) / len(scores)

# ── 函数② :评定等级 ──────────────────────────────
def get_grade(avg):
    # 根据平均分返回等级字符串
    if   avg >= 90: return "优秀 🏆"
    elif avg >= 80: return "良好 👍"
    elif avg >= 60: return "及格 📝"
    else:           return "不及格 ❌"

# ── 函数③ :打印单个学生报告 ─────────────────────
def print_report(student):
    # 调用前两个函数,打印一名学生的完整报告
    avg   = get_average(student["scores"])   # 调用函数①
    grade = get_grade(avg)                   # 调用函数②
    print(f" {student['name']:5s} | 平均:{avg:5.1f} | {grade}")

# ── 函数④ :打印全班报告 ────────────────────────
def print_class_report(students_list):
    # 遍历学生列表,为每人调用函数③
    print("=" * 38)
    print("      📊 数据2501班成绩报告单")
    print("=" * 38)
    for stu in students_list:
        print_report(stu)           # 调用函数③
    print("=" * 38)

# ── 主程序入口 ─────────────────────────────────
print_class_report(students)

# ======================================
#       📊 数据2501班成绩报告单
# ======================================
#  黎俊杰   | 平均: 89.0 | 良好 👍
#  李天宇   | 平均: 80.7 | 良好 👍
#  刘文财   | 平均: 95.0 | 优秀 🏆
#  陈扬     | 平均: 73.3 | 及格 📝
#  徐嘉豪   | 平均: 88.7 | 良好 👍
# ======================================

8

为什么要用函数?--- 有/无函数代码对比

❌ 不用函数(重复代码 × 3)

复制代码
# 计算甲的成绩
sa = [80, 90, 70]
ta = 0
for s in sa: ta += s
avg_a = ta / len(sa)

# 计算乙的成绩(复制粘贴😩)
sb = [60, 85, 95]
tb = 0
for s in sb: tb += s
avg_b = tb / len(sb)

# 计算丙的成绩(又复制粘贴😩)
sc = [99, 70, 88]
tc = 0
for s in sc: tc += s
avg_c = tc / len(sc)

✅ 用函数(一次定义,三次复用)

复制代码
# 只写一次!
def average(scores):
    return sum(scores) / len(scores)

# 复用三次,代码简洁优雅 ✨
avg_a = average([80, 90, 70])
avg_b = average([60, 85, 95])
avg_c = average([99, 70, 88])

# 需要改计算逻辑?
# 只改 average 函数内部一处 ✅
# 不需要找3处分别改 ❌

📋 函数的四大核心好处

好处 说明 实际效果
♻️ 代码复用 写一次,到处用 代码量减少 60%+
🎯 职责单一 每个函数只做一件事 逻辑清晰,好理解
🛠 易于维护 改 bug 只改函数内部 一处修改,全局生效
📖 可读性强 函数名就是注释 代码读起来像自然语言

9

Lambda 匿名函数--- 简单任务的"一行函数"

💡 当函数逻辑只有一行 时,可以用 lambda 简写,省去 def 和函数名。 常用于排序的 key 参数、map/filter 等场合。

lambda_demo.py

复制代码
# ── 普通 def 写法 vs Lambda 写法 对比 ──

def double_def(x):
    return x * 2

double_lambda = lambda x: x * 2
#              ↑参数  ↑冒号  ↑ 返回值(不需要 return 关键字)

print(double_def(5))      # 10
print(double_lambda(5))   # 10  —— 结果完全一样

# ── 实战:对学生按平均分排序 ──
students = [
    ("黎俊杰", 89), ("刘文财", 95),
    ("李天宇", 80), ("陈扬", 73)
]

# 按第2个元素(分数)降序排
students.sort(key=lambda stu: stu[1], reverse=True)
print(students)
# [('刘文财', 95), ('黎俊杰', 89), ('李天宇', 80), ('陈扬', 73)]

# ── lambda + map:对列表每个元素统一处理 ──
scores = [60, 70, 80, 90]
boosted = list(map(lambda s: s + 5, scores))
print(boosted)   # [65, 75, 85, 95]  每人加5分

10

初学者最容易犯的错误--- 错误代码 vs 正确代码对比

🚨 5 大高频错误清单

# 错误类型 ❌ 错误写法 ✅ 正确写法
1 定义了不调用 def say(): print("Hi") 程序结束没输出 末尾加 say() 才执行
2 调用时忘写括号 print(say) 打印的是函数对象,不是结果 print(say())
3 return后还写代码 return x print("never") return后的代码永远不执行 把 print 移到 return 之前
4 忘了接收返回值 add(3, 5) 结果算完就消失了 result = add(3, 5)
5 函数外用局部变量 函数内定义 x,外面 print(x) NameError 报错 用 return x 把值传出来

common_mistakes.py --- 错误演示与修正

复制代码
# ── 错误1:定义了不调用(无输出)──
def say():
    print("Hello")
# 以上代码运行不会输出任何东西!必须加:
say()          # ✅ 这样才会输出 Hello

# ── 错误2:忘写括号 ──
def get_name():
    return "黎俊杰"

print(get_name)    # ❌ 输出:<function get_name at 0x...>
print(get_name())   # ✅ 输出:黎俊杰

# ── 错误4:忘了接收返回值 ──
def add(a, b):
    return a + b

add(3, 5)            # ❌ 计算了但没存,结果消失!
result = add(3, 5)  # ✅ 存起来才能用
print(result)        # 8

# ── 错误5:函数外使用局部变量 ──
def calc():
    x = 42           # 局部变量,只在函数内
    return x        # ✅ 用 return 把它传出来

# print(x)          # ❌ NameError!
print(calc())       # ✅ 42

📌

快速参考卡--- 撕下来贴墙上

Python 函数速查卡 # 定义 def 函数名(参数): 函数体(缩进4格) return 结果 # 调用 变量 = 函数名(实参) # 参数类型速查 def f(必填, 默认=值, *args, **kwargs) # lambda 一行函数 f = lambda x: x * 2 # 作用域 全局变量 → 函数内外都能读 局部变量 → 只在函数内部存在 global 变量名 → 在函数内修改全局变量

🧩 自测题 --- 做完才算真懂了!

Q1:下面代码输出什么?

def add(a, b=10): return a + b
print(add(5))

输出:15。a=5,b 用默认值 10,5+10=15。

Q2:函数里的局部变量,在函数外面能直接使用吗?为什么?

不能。 局部变量的生命周期只在函数内部,函数执行结束后就销毁了。 在外面访问会报 NameError。 如果想在外面用这个值,需要用 return 把它传出来。

Q3:什么时候用 lambda,什么时候用 def?

用 lambda: 逻辑只有一行,临时使用,常见于 sort/map/filter 的 key 参数。

**用 def:**逻辑超过一行,需要复用、需要写文档字符串,优先用 def。 原则:简单 → lambda,复杂 → def。

Q4:写一个函数 greet_all(names),接收一个名字列表,打印每人的问候语。

def greet_all(names): for name in names: print(f"你好,{name}!欢迎来到数据2001班!") greet_all("李俊杰", "周洁伦", "刘的话", "陈东东", "徐嘻嘻")

相关推荐
guygg881 小时前
最大相关-最小冗余(mRMR)特征选择 MATLAB 实现
开发语言·matlab
郭涤生1 小时前
C++ 高性能编程最佳实践清单
开发语言·c++
烛衔溟1 小时前
TypeScript 类的静态成员与静态方法
开发语言·javascript·typescript
Nile1 小时前
解密Palantir系列一:4. Ontology 不是哲学
开发语言·前端·javascript
罗超驿2 小时前
15.JavaScript 函数与作用域完全指南:语法、参数、表达式与作用域链实战
开发语言·前端·javascript
.千余2 小时前
【C++】C++类与对象2:C++构造函数、运算符重载与流输入输出全面解析
c语言·开发语言·前端·c++·经验分享
郭涤生2 小时前
C++ 高性能状态机
开发语言·c++
卡次卡次12 小时前
vibecoding起步注意点:插件、Skills、MCP、Hooks
服务器·数据库·python·oracle
我的xiaodoujiao2 小时前
API 接口自动化测试详细图文教程学习系列24--如何用Pytest去设计接口测试用例并执行
python·学习·测试工具·pytest