💡 课堂例题
第 6 章 · 函数 · 共 8 题 · 代码均取自课堂讲稿
1
函数定义与调用
使用 def 定义函数,理解形参/实参、return 返回值、无return默认返回None。演示位置参数和关键字参数。
python
# 定义两数减法函数
def sub(x, y): # x和y是形参
return x - y
print(sub(1, 2)) # -1(1和2是实参)
print(sub(4, 6)) # -2
# 关键字参数
print(sub(y=1, x=2)) # 1
# 无参数函数
def list1():
for i in range(10):
print(f" {i} ", end="")
print()
# 没有return,返回值默认是None
list1() # 输出数字序列
print(list1()) # None
2
函数的参数:强制位置、命名关键字、默认值
演示 / 强制位置参数、* 命名关键字参数、带默认值的参数。注意默认值参数必须在最后。
python
# 强制位置参数(Python 3.8+),只能用位置传参
def sub1(x, y, /):
return x - y
print(sub1(2, 1)) # 1
# sub1(x=1, y=2) # 报错!
# 命名关键字参数,只能用"参数名=值"传参
def sub2(*, x, y):
return x - y
print(sub2(x=2, y=1)) # 1
# sub2(2, 1) # 报错!
# 带默认值的参数
def sub3(x=20, y=10):
return x - y
print(sub3()) # 10(使用默认值)
print(sub3(3, 3)) # 0(覆盖默认值)
3
可变参数 *args 和 **kwargs
*args 接收任意多个位置参数组装为元组,**kwargs 接收任意多个关键字参数组装为字典。
python
# 可变长度参数 *args
def add(*x):
return sum(x)
print(add(1, 2)) # 3
print(add(1, 2, 3, 4, 5)) # 15
# 可变关键字参数 **kwargs
def foo(*args, **kwargs):
print("位置参数:", args) # 元组
print("关键字参数:", kwargs) # 字典
foo(3, 2.1, True, name='骆昊', age=43, gpa=4.95)
# 位置参数: (3, 2.1, True)
# 关键字参数: {'name': '骆昊', 'age': 43, 'gpa': 4.95}
4
变量的作用域:局部、全局、嵌套
理解 LEGB 规则。global 关键字修改全局变量,nonlocal 关键字修改外层函数的变量。
python
# 全局变量
n = 100
def ex2():
global n # 声明要修改全局变量
n = n * 2
print("函数内部:", n)
ex2() # 函数内部: 200
print("函数外部:", n) # 函数外部: 200
# 嵌套作用域
def t2():
num = 10
def t3():
nonlocal num # 声明来自外层函数
num = num + 5
print("内层:", num)
t3()
print("外层:", num)
t2() # 内层: 15 / 外层: 15
# 内置作用域
print(len([1, 2, 3])) # 3 — len是内置函数
num = int("10")
print(num) # 10 — int是内置函数
5
递归函数:阶乘
递归三要素:明确函数功能 → 终止条件 → 等价关系式。演示 n! = n × (n-1)! 的递归实现。
python
def ni(n):
if n == 0 or n == 1: # 终止条件
return 1
else:
return n * ni(n - 1) # 等价关系式
print(ni(5)) # 120
# 计算过程: 5*ni(4) → 5*4*ni(3) → 5*4*3*ni(2) → 5*4*3*2*ni(1) → 5*4*3*2*1 = 120
# 递归输出 1→10 的两种写法
def num(n): # 正序:输出在递归前
if n <= 10:
print(n)
num(n + 1)
num(1) # 1 2 3 4 5 6 7 8 9 10
def num(n): # 输出在递归后(看似倒序)
if n >= 1:
num(n - 1)
print(n)
num(10) # 也是 1 2 3 4 5 6 7 8 9 10
6
理解递归调用过程
"递归前"在进入下层前执行(正序),"递归后"在从下层返回后执行(逆序)。体会栈的先入后出特性。
python
def p(n):
if n == 0:
return
print('递归前->', n) # 进入下一层之前执行
p(n - 1) # 递归调用
print('递归后->', n) # 从下一层返回之后执行
p(5)
# 输出:
# 递归前-> 5 ← 依次深入
# 递归前-> 4
# 递归前-> 3
# 递归前-> 2
# 递归前-> 1
# 递归后-> 1 ← 依次返回
# 递归后-> 2
# 递归后-> 3
# 递归后-> 4
# 递归后-> 5
7
lambda 匿名函数
lambda 参数: 表达式。一行定义简单函数,常搭配 map/filter/sorted/reduce 使用。演示各种参数形式。
python
# 基本用法
add = lambda x, y: x + y
print(add(1, 3)) # 4
# 直接调用
print((lambda x, y: x ** y)(5, 2)) # 25
# 搭配三元运算符
is_odd = lambda n: "奇数" if n % 2 != 0 else "偶数"
print(is_odd(7)) # 奇数
# 各种参数形式
func = lambda: "Hello!" # 无参数
func = lambda x: x ** 2 # 单参数
func = lambda x, y=2: x ** y # 默认参数
func = lambda *args: sum(args) # 可变参数
func = lambda **kw: len(kw) # 关键字可变参数
# lambda作为函数返回值
def make_operation(operator):
if operator == "+":
return lambda x, y: x + y
elif operator == "*":
return lambda x, y: x * y
add = make_operation("+")
print(add(3, 4)) # 7
mul = make_operation("*")
print(mul(3, 4)) # 12
8
高阶函数:map、filter、reduce、sorted
map 批量处理,filter 批量筛选,reduce 累积计算,sorted 排序。全部搭配 lambda 使用。
python
# map():将列表元素平方
nums = [1, 2, 3, 4, 5]
print(list(map(lambda x: x ** 2, nums))) # [1,4,9,16,25]
# 两个列表对应元素相加
print(list(map(lambda x, y: x + y, [10,20,30], [5,15,25]))) # [15,35,55]
# filter():筛选奇数
nums = [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(list(filter(lambda x: x % 2 != 0, nums))) # [1,3,5,7,9]
# 筛选长度>3的字符串
print(list(filter(lambda s: len(s) > 3, ["a","ab","abc","abcd"]))) # ['abcd']
# filter(None)过滤假值
print(list(filter(None, [0, 1, "", "hello", None, False]))) # [1,'hello']
# reduce():累积计算
from functools import reduce
print(reduce(lambda a, b: a + b, [1,2,3,4,5])) # 15(累加)
print(reduce(lambda a, b: a * b, [2,3,4,5])) # 120(累乘)
# 字符串拼接
print(reduce(lambda a, b: a + b, ["我","爱","Python"])) # 我爱Python
# sorted():自定义排序
arr = ['apple', 'banana', 'cherry', 'date']
print(sorted(arr, key=lambda s: len(s))) # 按长度排序
people = [{'name':'alice','age':15},{'name':'bob','age':25},{'name':'charlie','age':30}]
print(sorted(people, key=lambda x: x['age'])) # 按年龄排序