四、递归函数
4.1 递归基础
# 阶乘:n! = n * (n-1)!
def factorial(n):
"""递归计算阶乘"""
# 基线条件
if n <= 1:
return 1
# 递归条件
return n * factorial(n - 1)
print(f"5! = {factorial(5)}")
print(f"10! = {factorial(10)}")
# 斐波那契数列
def fibonacci(n):
"""递归计算斐波那契数"""
if n <= 1:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
print(f"fib(10) = {fibonacci(10)}")
# 递归限制
import sys
print(f"默认递归限制: {sys.getrecursionlimit()}")
# 修改递归限制
sys.setrecursionlimit(10000)
4.2 递归优化
# 1. 记忆化递归(缓存)
def fibonacci_memo(n, memo={}):
"""带缓存的斐波那契"""
if n in memo:
return memo[n]
if n <= 1:
return n
memo[n] = fibonacci_memo(n - 1, memo) + fibonacci_memo(n - 2, memo)
return memo[n]
print(f"fib_memo(40) = {fibonacci_memo(40)}")
# 2. 使用functools.lru_cache
from functools import lru_cache
@lru_cache(maxsize=128)
def fibonacci_cache(n):
if n <= 1:
return n
return fibonacci_cache(n - 1) + fibonacci_cache(n - 2)
print(f"fib_cache(50) = {fibonacci_cache(50)}")
print(f"缓存信息: {fibonacci_cache.cache_info()}")
# 3. 递归转迭代
def factorial_iterative(n):
result = 1
for i in range(2, n + 1):
result *= i
return result
def fibonacci_iterative(n):
if n <= 1:
return n
a, b = 0, 1
for _ in range(2, n + 1):
a, b = b, a + b
return b
print(f"factorial_iterative(10) = {factorial_iterative(10)}")
print(f"fibonacci_iterative(40) = {fibonacci_iterative(40)}")
4.3 经典递归示例
# 汉诺塔
def hanoi(n, source, target, auxiliary):
"""汉诺塔递归解法"""
if n == 1:
print(f"移动盘子 1 从 {source} 到 {target}")
return
hanoi(n - 1, source, auxiliary, target)
print(f"移动盘子 {n} 从 {source} 到 {target}")
hanoi(n - 1, auxiliary, target, source)
print("汉诺塔(3个盘子):")
hanoi(3, 'A', 'C', 'B')
# 二分查找(递归)
def binary_search(arr, target, left, right):
if left > right:
return -1
mid = (left + right) // 2
if arr[mid] == target:
return mid
elif arr[mid] > target:
return binary_search(arr, target, left, mid - 1)
else:
return binary_search(arr, target, mid + 1, right)
arr = [1, 3, 5, 7, 9, 11, 13]
index = binary_search(arr, 7, 0, len(arr) - 1)
print(f"查找7的位置: {index}")
# 遍历目录(递归)
import os
def list_files(directory, indent=0):
"""递归列出目录结构"""
for item in os.listdir(directory):
path = os.path.join(directory, item)
print(" " * indent + item)
if os.path.isdir(path):
list_files(path, indent + 1)
# list_files(".") # 列出当前目录
五、Lambda表达式
5.1 Lambda基础
# Lambda表达式:匿名函数
# 语法:lambda 参数: 表达式
# 基本Lambda
square = lambda x: x ** 2
print(square(5)) # 25
# 多个参数
add = lambda a, b: a + b
print(add(10, 20)) # 30
# 默认参数
power = lambda x, n=2: x ** n
print(power(5)) # 25
print(power(5, 3)) # 125
# 无参数Lambda
hello = lambda: "Hello, World!"
print(hello())
# 立即调用
result = (lambda x, y: x * y)(5, 6)
print(result) # 30
# Lambda表达式限制:只能包含单个表达式
# 不能包含语句、赋值、循环等
# 错误示例:
# lambda x: x = x + 1 # 不能赋值
# lambda x: if x > 0: return x # 不能使用if语句
5.2 Lambda与高阶函数
# map():将函数应用于每个元素
numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x ** 2, numbers))
print(f"平方: {squared}")
# filter():过滤元素
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(f"偶数: {evens}")
# sorted():自定义排序
students = [
{"name": "张三", "score": 85},
{"name": "李四", "score": 92},
{"name": "王五", "score": 78}
]
sorted_by_score = sorted(students, key=lambda s: s["score"], reverse=True)
print(f"按分数排序: {sorted_by_score}")
# reduce():累积计算
from functools import reduce
product = reduce(lambda a, b: a * b, numbers)
print(f"乘积: {product}")
# max()/min():使用key参数
words = ["apple", "banana", "pear", "watermelon"]
longest = max(words, key=lambda w: len(w))
print(f"最长的单词: {longest}")
5.3 Lambda的实际应用
# 列表排序(多条件)
people = [
("张三", 25),
("李四", 30),
("王五", 25),
("赵六", 28)
]
# 按年龄排序,年龄相同按姓名排序
sorted_people = sorted(people, key=lambda p: (p[1], p[0]))
print(f"排序后: {sorted_people}")
# 字典值排序
scores = {"张三": 85, "李四": 92, "王五": 78, "赵六": 88}
sorted_by_score = sorted(scores.items(), key=lambda item: item[1], reverse=True)
print(f"分数排行: {sorted_by_score}")
# 事件处理(GUI)
import tkinter as tk
root = tk.Tk()
button = tk.Button(root, text="点击", command=lambda: print("按钮被点击"))
# button.pack()
# root.mainloop()
# 数据转换
data = ["1", "2", "3", "4", "5"]
numbers = list(map(int, data))
print(f"转换后: {numbers}")
# 条件过滤与转换
numbers = [-5, -3, 0, 2, 4, 6]
positive_squares = list(map(lambda x: x ** 2, filter(lambda x: x > 0, numbers)))
print(f"正数的平方: {positive_squares}")
六、装饰器
6.1 装饰器基础
# 装饰器:在不修改函数代码的情况下增加功能
# 最简单的装饰器
def my_decorator(func):
def wrapper():
print("函数执行前")
func()
print("函数执行后")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
# 装饰带参数的函数
def timer_decorator(func):
import time
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"{func.__name__} 执行时间: {end - start:.4f}秒")
return result
return wrapper
@timer_decorator
def slow_function(n):
total = 0
for i in range(n):
total += i
return total
result = slow_function(1000000)
print(f"结果: {result}")
# 带参数的装饰器
def repeat(times):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(times):
result = func(*args, **kwargs)
return result
return wrapper
return decorator
@repeat(3)
def greet(name):
print(f"Hello, {name}!")
greet("Python")
6.2 多个装饰器
# 多个装饰器的执行顺序(从下往上)
def decorator_a(func):
def wrapper():
print("A开始")
func()
print("A结束")
return wrapper
def decorator_b(func):
def wrapper():
print("B开始")
func()
print("B结束")
return wrapper
@decorator_a
@decorator_b
def my_func():
print("执行函数")
print("多个装饰器示例:")
my_func()
# 输出顺序: A开始 -> B开始 -> 执行函数 -> B结束 -> A结束
# 实际应用:认证与日志
def require_auth(func):
def wrapper(*args, **kwargs):
# 模拟认证
if not hasattr(wrapper, "authenticated"):
print("需要认证")
return None
return func(*args, **kwargs)
return wrapper
def log_call(func):
def wrapper(*args, **kwargs):
print(f"调用函数: {func.__name__}")
print(f"参数: args={args}, kwargs={kwargs}")
return func(*args, **kwargs)
return wrapper
@log_call
@require_auth
def secret_function(user):
return f"秘密数据给{user}"
# secret_function("admin")
6.3 类装饰器
# 类作为装饰器
class CountCalls:
def __init__(self, func):
self.func = func
self.count = 0
def __call__(self, *args, **kwargs):
self.count += 1
print(f"函数 {self.func.__name__} 被调用 {self.count} 次")
return self.func(*args, **kwargs)
@CountCalls
def say_hello(name):
print(f"Hello, {name}!")
say_hello("张三")
say_hello("李四")
say_hello("王五")
# 带参数的类装饰器
class Repeat:
def __init__(self, times):
self.times = times
def __call__(self, func):
def wrapper(*args, **kwargs):
for _ in range(self.times):
result = func(*args, **kwargs)
return result
return wrapper
@Repeat(3)
def greet(name):
print(f"Hi, {name}!")
greet("Python")
6.4 functools.wraps
from functools import wraps
# 不使用wraps会丢失原函数信息
def bad_decorator(func):
def wrapper():
"""装饰器包装函数"""
return func()
return wrapper
# 使用wraps保留原函数信息
def good_decorator(func):
@wraps(func)
def wrapper():
"""装饰器包装函数"""
return func()
return wrapper
@bad_decorator
def original_func():
"""原始函数文档"""
print("执行原函数")
@good_decorator
def wrapped_func():
"""原始函数文档"""
print("执行原函数")
print(f"bad_decorator: {original_func.__name__}, {original_func.__doc__}")
print(f"good_decorator: {wrapped_func.__name__}, {wrapped_func.__doc__}")
# 完整的装饰器模板
def my_decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
# 函数执行前的操作
result = func(*args, **kwargs)
# 函数执行后的操作
return result
return wrapper
6.5 装饰器实际应用
import time
from functools import wraps
# 1. 性能计时器
def timer(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = func(*args, **kwargs)
end = time.perf_counter()
print(f"{func.__name__} 耗时: {end - start:.6f}秒")
return result
return wrapper
# 2. 缓存(Memoization)
def cache(func):
memo = {}
@wraps(func)
def wrapper(*args):
if args in memo:
return memo[args]
result = func(*args)
memo[args] = result
return result
return wrapper
@cache
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
# 3. 重试机制
def retry(max_retries=3, delay=1):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
for attempt in range(max_retries):
try:
return func(*args, **kwargs)
except Exception as e:
if attempt == max_retries - 1:
raise
print(f"重试 {attempt + 1}/{max_retries}")
time.sleep(delay)
return None
return wrapper
return decorator
@retry(max_retries=3, delay=0.5)
def unstable_network_call():
import random
if random.random() < 0.7:
raise ConnectionError("网络错误")
return "成功"
# 4. 权限检查
def require_permission(permission):
def decorator(func):
@wraps(func)
def wrapper(user, *args, **kwargs):
if user.get("permissions", []) and permission in user["permissions"]:
return func(user, *args, **kwargs)
else:
raise PermissionError(f"需要 {permission} 权限")
return wrapper
return decorator
@require_permission("admin")
def delete_user(user, user_id):
print(f"删除用户 {user_id}")
# 5. 日志记录
def log_call(logger=None):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
print(f"调用: {func.__name__}")
print(f"参数: args={args}, kwargs={kwargs}")
result = func(*args, **kwargs)
print(f"返回: {result}")
return result
return wrapper
return decorator
@log_call()
def add(a, b):
return a + b
# 使用示例
@timer
def compute():
time.sleep(0.5)
return 42
@timer
@cache
def expensive_compute(n):
time.sleep(0.1)
return n * n
print(compute())
print(fibonacci(30))
print(expensive_compute(10))
print(expensive_compute(10)) # 使用缓存