第7讲 · 函数 · 15分钟

第7讲 函数:封装与复用

用定义、参数与返回值,把代码整理成可复用的工具。

1定义与调用:功能先命名,再使用
2参数与返回值:数据进去,结果出来
3作用域:变量在哪里有效
知识点精讲随堂快练本讲练习

函数是什么:一段有名字的功能

概念建立

1函数是一组完成特定任务的语句
2定义只登记功能;调用才执行函数体
3print()是现成函数,我们也能自己定义

语法拆解

print('你好')
调用已有函数
greet('小林')
调用自己定义的函数

循环解决当前位置的重复执行;函数解决不同位置的复用。两者可以配合。

def:函数头、函数体与调用

l07_first_function.py
def greet(name):
    return "你好," + name

print(greet("小林"))
def greet(name):
def、合法函数名、英文括号和冒号
return '你好,' + name
缩进的函数体,return交回结果
print(greet('小林'))
调用后把返回值交给print显示

语法拆解

1def 函数名(形参列表):
2函数体统一缩进;需要结果时写return
3恢复顶格写函数名(实参列表)进行调用

四步走:定义 → 调用 → 执行 → 返回

①定义:记录功能,不执行函数体 · ②调用:把实参交给形参;③执行:进入函数体 · ④返回:回到调用处,继续主程序

l07_define_only.py
def greet():
    print("函数体执行")

print("主程序继续")
l07_define_call.py
def greet():
    print("函数体执行")

greet()
print("主程序继续")

原课件的“哪里调用,就返回哪里”是理解执行路径的关键。

位置参数:形参与实参依次对应

l07_positional.py
def describe(name, score):
    return name + "的分数是" + str(score)

print(describe("小林", 80))
print(describe("小周", 95))
def describe(name, score):
两个形参,先姓名后分数
describe('小林', 80)
两个实参按位置传入

参数传递

1定义时的name、score是形参
2调用时的“小林”、80是实参
3默认按位置一一对应,数量也要匹配

默认参数:省略时使用预设值

l07_default.py
def greet(name, suffix="同学"):
    return "你好," + name + suffix

print(greet("小林"))
print(greet("陈", "老师"))
def greet(name, suffix='同学'):
name必填,suffix可选
greet('小林')
suffix取默认值
greet('陈老师', '老师')
显式传值覆盖默认值

参数传递

1可选参数在定义时写“参数=默认值”
2调用时不传它,就使用默认值
3必填参数写在默认参数前面

关键字参数:点名传递更清楚

l07_keyword.py
def describe(name, score=60):
    return f"{name}:{score}分"

print(describe("小林", 80))
print(describe(score=80, name="小林"))
describe(score=80, name='小林')
按名字匹配,不再靠先后位置

参数传递

1调用时写“形参名=实参”
2关键字参数可以改变书写顺序
3位置参数要放在关键字参数前

拓展:Python还允许用*args接收可变数量的位置实参;本讲先掌握固定与默认参数。

return:可以交回零个、一个或多个结果

return会结束本次调用,并把值放回调用位置 · 无显式return时,调用表达式的值是None · return a, b交回两个结果,可分别接收

l07_return_many.py
def calculate(a, b):
    return a + b, a - b

total, difference = calculate(8, 3)
print("和:", total)
print("差:", difference)
l07_no_return.py
def announce():
    print("已记录")

result = announce()
print("返回值:", result)

更精确地说,return a, b返回的是一个元组,可用两个变量拆包。

print ≠ return:看见不等于接到

l07_print_return.py
def show_total():
    print(24)

def get_total():
    return 24

shown = show_total()
received = get_total()
print("只打印得到:", shown)
print("真正返回得到:", received + 5)

易错辨析

1print只显示内容
2return才让调用者拿到结果
3想继续计算,应返回数值再由主程序显示

局部变量:只在本次函数内部有效

l07_local.py
label = "外层"

def make_label(name):
    label = "学员:" + name
    return label

print(make_label("小林"))
print(label)

变量作用域

1在函数内赋值的变量通常是局部变量
2函数结束后,局部变量不能在外部直接使用
3同名局部变量不会自动改写外部变量

不要在函数外直接写print(name)或print(函数里的label),它们不在外部作用域。

全局变量:读取与重新赋值要分开

l07_global.py
course = "Python"
def show_course():
    print(course)
def rename_course():
    global course
    course = "Python进阶"
show_course()
rename_course()
show_course()
global course
声明后,函数内赋值会作用于外部同名变量

变量作用域

1函数外定义的变量是全局变量
2函数内部只读取全局变量不需要global
3要在函数内重新绑定全局变量,先写global

原课件把global说成“在函数内部使用全局变量时必须声明”,这里按实际规则修正:读取不用;重新赋值才用。优先用参数和return传数据,减少global修改。

快练1:定义后会自动执行吗?

l07_quiz_def.py
def ping():
    print("函数运行")

print("准备好了")
ping()

随堂练习

1先预测屏幕输出
2指出定义与调用分别在哪里
3解释def是定义函数的关键字
答案与判断依据点击展开
print("准备好了")
ping()  # 这里才执行函数体

定义关键字是def;只定义不调用,不会执行函数体。

主程序先打印“准备好了”,调用ping()后才进入函数体。

快练2:return的三种情况

l07_quiz_return.py
def first():
    print(1)

def second():
    return 2

def third():
    return 3, 4

print(first())
print(second() + 5)
print(third())

随堂练习

1预测三个函数调用的结果
2无return、单值return、多值return
3说出哪个调用结果能继续参与计算
答案与判断依据点击展开
first()   # 打印1,返回None
second()  # 返回2,可继续计算
third()   # 返回元组(3, 4)

函数可以没有return,也可以有多个return语句,但一次调用只会执行到其中一个。

return可以交回多个值;原课件第二、三题中“必须返回值”“只能返回一个值”都不成立。

快练3:默认值、关键字与作用域

l07_quiz_scope.py
result = "外部"

def check(score, threshold=60):
    result = score >= threshold
    return result

print(check(60))
print(check(threshold=80, score=75))
print(result)

随堂练习

1两次调用各用了哪个threshold?
2函数内的result是否改写了外部result?
3判断“函数必须有返回值”为什么错
答案与判断依据点击展开
check(60)                       # 默认阈值60,True
check(threshold=80, score=75)  # 按名字传参,False
print(result)                   # 外部变量仍是“外部”

默认参数可以省略,关键字参数按名称匹配。

函数内result是局部变量,没有改写外部result。

函数可以没有显式return;Python会隐式返回None。可变数量参数也是合法扩展写法。

本讲练习:可配置的成绩评语

l07_evaluate_start.py
def evaluate(name, score, pass_score=60):
    # 1. 判断是否达标,保存为status
    # 2. 生成“姓名:状态”评语message
    # 3. 同时返回status和message
    pass

# 位置调用:小林,60分,使用默认阈值
# 关键字调用:小周,75分,阈值80
# 分别输出两人的状态和评语

独立练习

1定义evaluate(name, score, pass_score=60)
2达到阈值返回“达标”,否则返回“待达标”
3同时返回状态和评语;用位置与关键字两种方式调用

自测:小林60分应达标;小周75分、阈值80应待达标。保留代码截图、两组运行截图与简短AI检查记录。

参考实现:沿数据流读懂函数

l07_evaluate_answer.py
def evaluate(name, score, pass_score=60):
    if score >= pass_score:
        status = "达标"
    else:
        status = "待达标"
    message = f"{name}:{status}"
    return status, message
status1, message1 = evaluate("小林", 60)
status2, message2 = evaluate(name="小周", score=75, pass_score=80)
print(status1, message1)
print(status2, message2)

练习讲评与总结

1实参进入形参,默认值或关键字决定阈值
2局部status、message在函数内生成
3return交回两个结果,主程序再决定如何显示

课后迁移:再测59、60、61三个边界分数;优先用参数和返回值交换数据,不依赖global改写。

课堂 Python 解释器
点击“逐步运行”后,这里会显示结果。
Python:按执行步骤显示结果。