第8章:函数(Functions)
一、导读
1.1 本章学习目标
第8章介绍Python的函数机制。本章核心目标:
- 掌握函数定义和调用:def关键字
- 理解参数传递:位置参数、关键字参数、默认参数
- 掌握可变参数:*args和**kwargs
- 学会使用lambda表达式:匿名函数
- 理解作用域:局部变量和全局变量
- 掌握模块导入:import和from...import
1.2 为什么本章如此重要
函数是代码复用的基本单位。Python的函数功能强大,支持多种参数传递方式、闭包、装饰器等高级特性。理解函数的设计原则,才能编写出清晰、可维护的代码。
1.3 核心问题引导
Python的函数参数是如何传递的?是值传递还是引用传递?
*args和**kwargs有什么区别?各自适合什么场景?
lambda表达式和普通函数有什么本质区别?
全局变量和局部变量的作用域规则是什么?
二、核心概念详解
8.1 函数基础
python
# 函数定义
def greet(name, greeting="Hello"):
"""向用户打招呼(文档字符串)"""
return f"{greeting}, {name}!"
print(greet("Alice")) # Hello, Alice!
print(greet("Bob", "Hi")) # Hi, Bob!
print(greet(greeting="Hey", name="Charlie")) # Hey, Charlie!
# 查看文档
print(greet.__doc__)
help(greet)8.2 参数传递
python
# 位置参数
def describe_pet(name, animal_type="dog"):
print(f"I have a {animal_type} named {name}")
describe_pet("Buddy") # 使用默认值
describe_pet("Whiskers", "cat") # 位置参数
describe_pet(animal_type="fish", name="Nemo") # 关键字参数
# 可变参数 *args
def sum_all(*args):
"""计算所有参数的和"""
return sum(args)
print(sum_all(1, 2, 3)) # 6
print(sum_all(1, 2, 3, 4, 5)) # 15
# 关键字可变参数 **kwargs
def build_profile(**kwargs):
"""构建用户档案"""
return kwargs
profile = build_profile(name="Alice", age=20, city="Beijing")
print(profile) # {'name': 'Alice', 'age': 20, 'city': 'Beijing'}
# 混合使用
def func(a, b, *args, **kwargs):
print(f"a={a}, b={b}")
print(f"args={args}")
print(f"kwargs={kwargs}")
func(1, 2, 3, 4, 5, x=10, y=20)8.3 返回值
python
# 返回单个值
def square(x):
return x ** 2
# 返回多个值(实际返回元组)
def min_max(numbers):
return min(numbers), max(numbers)
lo, hi = min_max([3, 1, 4, 1, 5])
print(f"Min: {lo}, Max: {hi}")
# 没有return的函数返回None
def do_nothing():
pass
result = do_nothing()
print(result) # None
# 提前返回
def divide(a, b):
if b == 0:
return None # 或者抛出异常
return a / b8.4 作用域
python
# 局部变量和全局变量
x = 10 # 全局变量
def outer():
x = 20 # 外层函数的局部变量
def inner():
nonlocal x # 引用外层函数的变量
x = 30
print(f"inner: x = {x}")
inner()
print(f"outer: x = {x}")
outer()
print(f"global: x = {x}")
# global关键字
count = 0
def increment():
global count
count += 1
increment()
increment()
print(count) # 2
# 最佳实践:尽量避免使用global
def better_increment(current_count):
return current_count + 1
count = better_increment(count)8.5 Lambda表达式
python
# 基本lambda
square = lambda x: x ** 2
print(square(5)) # 25
# 多参数
add = lambda a, b: a + b
print(add(3, 5)) # 8
# 与高阶函数配合
numbers = [1, 2, 3, 4, 5]
# map
squared = list(map(lambda x: x**2, numbers))
print(squared) # [1, 4, 9, 16, 25]
# filter
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens) # [2, 4]
# sorted
students = [("Alice", 90), ("Bob", 85), ("Charlie", 92)]
sorted_students = sorted(students, key=lambda s: s[1], reverse=True)
print(sorted_students)
# 立即调用的lambda
result = (lambda x, y: x + y)(3, 5)
print(result) # 88.6 模块
python
# 导入整个模块
import math
print(math.sqrt(16)) # 4.0
print(math.pi) # 3.14159...
# 导入特定函数
from math import sqrt, pi
print(sqrt(16))
# 导入并重命名
from datetime import datetime as dt
now = dt.now()
print(now)
# 导入所有(不推荐)
# from math import *
# 自定义模块
# 假设 mymodule.py 中有:
# def add(a, b):
# return a + b
# PI = 3.14159
# import mymodule
# print(mymodule.add(1, 2))
# print(mymodule.PI)三、实战案例
3.1 装饰器
python
import time
import functools
def timer(func):
"""计时装饰器"""
@functools.wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"{func.__name__} took {end - start:.4f}s")
return result
return wrapper
def memoize(func):
"""缓存装饰器"""
cache = {}
@functools.wraps(func)
def wrapper(*args):
if args not in cache:
cache[args] = func(*args)
return cache[args]
return wrapper
@timer
@memoize
def fibonacci(n):
if n < 2:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
print(fibonacci(30))四、本章小结
第8章介绍了Python函数:定义和调用、参数传递(位置/关键字/默认/可变)、返回值、作用域、lambda表达式、模块导入。函数是代码复用的核心。
五、思考与练习
思考题
Python的函数参数传递机制是什么?
*args和**kwargs在函数定义和调用时有什么不同?
闭包是什么?lambda能形成闭包吗?
装饰器的原理是什么?
编程练习
实现一个带参数验证的函数装饰器。
编写一个递归函数计算阶乘。
实现一个简单的缓存装饰器。