第 7 章 函数
学习目标
- 会用
def定义函数、用return返回结果 - 掌握默认参数、关键字参数、
*args、**kwargs - 理解局部变量与全局变量的作用域
- 认识 lambda 与递归(选学)
7.1 定义与调用
函数是一段有名字、可重复调用的代码。用 def 定义:
def greet(name):
return f"你好,{name}!"
print(greet("小明"))输出:
你好,小明!语法要点:
def后面跟函数名、括号和冒号。- 括号里是参数(函数需要的输入),
name在这里是形参。 return把计算结果返回给调用者。- 调用时在函数名后加括号并传入实参:
greet("小明")。
return 是可省略的。没有 return(或只有 return 不带值)的函数,返回值是 None:
def nothing():
pass
print(nothing())输出:
NoneNone 是 Python 表示「什么都没有」的特殊值。
7.2 参数
默认参数:定义时给参数指定默认值,调用时可以不传:
def power(base, exp=2):
return base ** exp
print(power(3)) # exp 用默认值 2
print(power(2, 10)) # 显式传入 exp输出:
9
1024关键字参数:调用时用 参数名=值 的形式,可以不按顺序传:
print(power(exp=3, base=2))输出:
8*args:收集任意数量的位置参数,在函数内是一个元组:
def add_all(*nums):
return sum(nums)
print(add_all(1, 2, 3))
print(add_all(1, 2, 3, 4, 5))输出:
6
15**kwargs:收集任意数量的关键字参数,在函数内是一个字典:
def show(**kwargs):
return kwargs
print(show(name="小明", age=18))输出:
{'name': '小明', 'age': 18}*args 与 **kwargs 是约定俗成的名字,常用于「不知道调用者会传多少参数」的场景,例如日志、配置收集。
返回值可以有多个——实际返回的是一个元组,调用时用多个变量接收即可:
def minmax(lst):
return min(lst), max(lst)
lo, hi = minmax([3, 1, 2])
print(lo, hi)输出:
1 37.3 作用域
作用域决定一个名字在哪些地方可以被访问。函数内部定义的变量叫局部变量,只存在于函数内部;函数外定义的叫全局变量。
def f():
x = 10 # 局部变量,函数外不可见
print(x) # 报错:NameError: name 'x' is not defined函数内可以读取全局变量,但想修改它必须用 global 声明:
count = 0
def add_one():
global count
count += 1
add_one()
add_one()
print(count)输出:
2不加 global 时,count += 1 会被当成「创建一个新的局部变量 count」,函数外的 count 不会被修改。规则简单记:默认情况下,函数内只能读全局变量,不能改。
7.4 lambda(选学)
lambda 用来写「一句话的函数」,即只有一个表达式、自动返回结果的小函数:
double = lambda x: x * 2
print(double(4))输出:
8等价于:
def double(x):
return x * 2lambda 最常见的用途是作为参数传给其他函数。例如 sorted 的 key 参数指定排序依据:
words = ["banana", "apple", "cherry"]
print(sorted(words, key=len))输出:
['apple', 'banana', 'cherry']按长度排序,而不是默认的字典序。等价的具名函数写法是 def by_len(w): return len(w);lambda 只是更短。
7.5 递归(选学)
递归指函数调用自身。递归必须有终止条件,否则会无限调用直至报错。经典例子:阶乘 n! = n × (n-1)!。
def fact(n):
if n <= 1:
return 1
return n * fact(n - 1)
print(fact(5))输出:
120计算过程:fact(5) → 5 * fact(4) → 5 * 4 * fact(3) → … → 5 × 4 × 3 × 2 × 1 = 120。if n <= 1: return 1 是终止条件。递归能简洁地表达分治类问题,但注意:递归层数过深会报 RecursionError。
动手实践
任务:把前面章节的程序改造成函数。 第 2 章的温度换算、第 6 章的成绩统计,各写成一个函数。
def celsius_to_fahrenheit(c):
return c * 9 / 5 + 32
def score_report(text):
scores = [int(x) for x in text.split(",")]
return {
"平均分": sum(scores) / len(scores),
"最高分": max(scores),
"最低分": min(scores),
"及格人数": len([s for s in scores if s >= 60]),
}
print(celsius_to_fahrenheit(25))
print(score_report("85,92,78,90,66"))输出:
77.0
{'平均分': 82.2, '最高分': 92, '最低分': 66, '及格人数': 5}函数的好处:一次写好,到处调用;想改逻辑只需改一处。
常见错误
| 错误写法 | 报错信息 | 原因 |
|---|---|---|
def f(a, b): ... 然后 f(1) | TypeError: f() missing 1 required positional argument: 'b' | 实参个数少于形参 |
f(1, 2, 3)(形参只有 2 个) | TypeError: f() takes 2 positional arguments but 3 were given | 实参个数多于形参 |
函数内 x = 10,函数外 print(x) | NameError: name 'x' is not defined | x 是局部变量,外面不可见 |
函数内直接 count += 1 修改全局变量 | 不报错但全局变量没变 | 修改全局变量需要 global 声明 |
忘记写 return,结果总是 None | 不报错但结果不对 | 检查是否漏了 return |
章末练习
基础
- 写函数
is_even(n),返回n是否为偶数。 - 写函数
circle_area(r),返回半径为r的圆面积(3.14 * r ** 2),调用时输出半径 5 的结果。 - 写函数
repeat(text, times=2),返回text重复times次的字符串;分别用repeat("ha")和repeat("ha", 3)调用并输出。
提高
- 写函数
average(*nums),返回所有参数的平均值,并用average(1, 2, 3, 4)验证(结果是 2.5)。 - 写函数
count_chars(text),返回一个字典,记录text中每个字符出现的次数,如count_chars("hello")返回{"h": 1, "e": 1, "l": 2, "o": 1}。提示:遍历字符串,字典计数。
挑战
- 用递归写函数
fib(n),返回斐波那契数列第n项(第 1、2 项为 1,之后每项是前两项之和),验证fib(10)等于 55。 - 写出
sorted(["bb", "a", "ccc"], key=len)的结果,再写一个等价效果的 lambda 表达式,运行验证。
章末自测
每题选择一个最佳答案。本书不附答案:完成后交由老师或 AI 老师批改讲解。
- 定义函数的关键字是?
- A.
func - B.
def - C.
function - D.
fn
- A.
- 函数没有
return时,返回值是?- A.
0 - B.
None - C. 报错
- D.
False
- A.
def power(base, exp=2): return base ** exp,power(3)的结果是?- A.
6 - B.
9 - C.
8 - D. 报错
- A.
- 调用
f(exp=3, base=2)使用的是?- A. 位置参数
- B. 关键字参数
- C. 默认参数
- D. 全局参数
*args在函数内是?- A. 列表
- B. 元组
- C. 字典
- D. 字符串
- 函数内定义的变量是?
- A. 全局变量
- B. 局部变量
- C. 常量
- D. 内置变量
- 函数内要修改全局变量,需要?
- A. 直接用即可
- B.
global声明 - C.
nonlocal声明 - D. 重新定义
lambda x: x * 2等价于?- A.
def f(x): return x * 2 - B.
def f(x): x * 2 - C.
return x * 2 - D. 一个列表
- A.
- 递归函数最重要的是要有?
- A.
for循环 - B. 终止条件
- C. 全局变量
- D. lambda
- A.
fact(5)(阶乘函数)的结果是? A.15B.120C.25D.720
