—— 代码复用的艺术
# 定义函数
def greet(name: str) -> str:
"""打招呼函数(docstring)"""
return f"你好,{name}!"
# 调用
msg = greet("张三")
print(msg) # 你好,张三!
# 多返回值(实际返回元组)
def min_max(numbers):
return min(numbers), max(numbers)
lo, hi = min_max([3, 1, 4, 1, 5])
print(f"最小={lo}, 最大={hi}") # 最小=1, 最大=5
# 1. 位置参数
def power(base, exp):
return base ** exp
print(power(2, 10)) # 1024
# 2. 关键字参数
print(power(exp=10, base=2)) # 1024 顺序无关
# 3. 默认参数
def connect(host, port=3306, timeout=30):
return f"{host}:{port} (超时{timeout}s)"
print(connect("localhost")) # localhost:3306 (超时30s)
print(connect("db.com", port=5432)) # db.com:5432 (超时30s)
# 4. 可变位置参数 *args
def total(*numbers):
return sum(numbers)
print(total(1, 2, 3, 4)) # 10
# 5. 可变关键字参数 **kwargs
def make_profile(**info):
for k, v in info.items():
print(f" {k}: {v}")
make_profile(name="张三", age=28, city="北京")
# 6. 仅位置参数 (/) 和仅关键字参数 (*)
def func(a, b, /, c, d, *, e, f):
"""
a, b: 仅位置参数(不能用作关键字)
c, d: 位置或关键字
e, f: 仅关键字参数(必须用关键字)
"""
return a + b + c + d + e + f
print(func(1, 2, 3, 4, e=5, f=6)) # 21
# ❌ 错误写法
def append_to(item, lst=[]):
lst.append(item)
return lst
# ✅ 正确写法
def append_to(item, lst=None):
if lst is None:
lst = []
lst.append(item)
return lst
# lambda: 匿名函数
square = lambda x: x ** 2
print(square(5)) # 25
# 排序中使用 lambda
students = [("张三", 85), ("李四", 92), ("王五", 78)]
students.sort(key=lambda s: s[1], reverse=True)
print(students) # [('李四', 92), ('张三', 85), ('王五', 78)]
# map: 映射
nums = [1, 2, 3, 4]
squares = list(map(lambda x: x**2, nums))
print(squares) # [1, 4, 9, 16]
# filter: 过滤
evens = list(filter(lambda x: x % 2 == 0, nums))
print(evens) # [2, 4]
# reduce: 累积
from functools import reduce
product = reduce(lambda a, b: a * b, nums)
print(product) # 24
# sorted: 返回新列表(不修改原列表)
sorted_nums = sorted([3, 1, 4, 1, 5])
print(sorted_nums) # [1, 1, 3, 4, 5]
装饰器是 Python 最强大的特性之一——在不修改函数代码的情况下,增强函数功能。
import time
import functools
def timer(func):
"""计时装饰器:测量函数执行时间"""
@functools.wraps(func) # 保留原函数元信息
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = func(*args, **kwargs)
elapsed = time.perf_counter() - start
print(f"[{func.__name__}] 耗时: {elapsed:.4f}s")
return result
return wrapper
@timer
def slow_sum(n):
"""计算1到n的和"""
return sum(range(n + 1))
result = slow_sum(1000000)
# [slow_sum] 耗时: 0.0234s
def retry(max_attempts=3, delay=1):
"""重试装饰器:失败自动重试"""
import time
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
for attempt in range(1, max_attempts + 1):
try:
return func(*args, **kwargs)
except Exception as e:
if attempt == max_attempts:
raise
print(f"第{attempt}次失败: {e},{delay}s后重试...")
time.sleep(delay)
return wrapper
return decorator
@retry(max_attempts=3, delay=0.5)
def unstable_api():
import random
if random.random() < 0.7:
raise ConnectionError("网络错误")
return "成功"
# 缓存装饰器
from functools import lru_cache
@lru_cache(maxsize=128)
def fibonacci(n):
if n < 2:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
print(fibonacci(50)) # 瞬间出结果!
# 类型检查装饰器
def typecheck(**expected):
def decorator(func):
@functools.wraps(func)
def wrapper(**kwargs):
for name, typ in expected.items():
if name in kwargs and not isinstance(kwargs[name], typ):
raise TypeError(
f"{name} 应为 {typ.__name__},实际为 {type(kwargs[name]).__name__}"
)
return func(**kwargs)
return wrapper
return decorator
@typecheck(name=str, age=int)
def register(name, age):
return f"{name}, {age}岁 已注册"
# LEGB 规则: Local → Enclosing → Global → Built-in
x = "global"
def outer():
x = "enclosing"
def inner():
x = "local"
print(x) # local
inner()
print(x) # enclosing
outer()
print(x) # global
# 闭包: 函数记住外部变量
def make_counter(start=0):
count = start
def counter():
nonlocal count
count += 1
return count
return counter
c = make_counter(10)
print(c()) # 11
print(c()) # 12
print(c()) # 13
#!/usr/bin/env python3
"""第04课 函数验证"""
import functools
import time
def test_params():
"""参数类型测试"""
def power(base, exp=2):
return base ** exp
assert power(3) == 9
assert power(2, 10) == 1024
assert power(exp=3, base=2) == 8
def total(*nums):
return sum(nums)
assert total(1, 2, 3) == 6
def build(**kw):
return kw
assert build(a=1, b=2) == {"a": 1, "b": 2}
print("✅ 参数类型测试通过")
def test_return():
"""返回值测试"""
def min_max(nums):
return min(nums), max(nums)
lo, hi = min_max([3, 1, 4])
assert lo == 1 and hi == 4
print("✅ 返回值测试通过")
def test_lambda():
"""Lambda测试"""
nums = [3, 1, 4, 1, 5]
assert sorted(nums) == [1, 1, 3, 4, 5]
squares = list(map(lambda x: x**2, [1,2,3]))
assert squares == [1, 4, 9]
evens = list(filter(lambda x: x%2==0, range(10)))
assert evens == [0, 2, 4, 6, 8]
from functools import reduce
product = reduce(lambda a,b: a*b, [1,2,3,4])
assert product == 24
print("✅ Lambda测试通过")
def test_decorator():
"""装饰器测试"""
def timer(func):
@functools.wraps(func)
def wrapper(*a, **kw):
start = time.perf_counter()
result = func(*a, **kw)
elapsed = time.perf_counter() - start
return result, elapsed
return wrapper
@timer
def add(a, b):
return a + b
result, elapsed = add(3, 4)
assert result == 7
assert elapsed >= 0
assert add.__name__ == "add" # functools.wraps 保留函数名
print("✅ 装饰器测试通过")
def test_closure():
"""闭包测试"""
def make_counter(start=0):
count = start
def counter():
nonlocal count
count += 1
return count
return counter
c = make_counter(10)
assert c() == 11
assert c() == 12
assert c() == 13
print("✅ 闭包测试通过")
def test_lru_cache():
"""缓存装饰器测试"""
from functools import lru_cache
call_count = 0
@lru_cache(maxsize=100)
def fib(n):
nonlocal call_count
call_count += 1
if n < 2:
return n
return fib(n-1) + fib(n-2)
assert fib(30) == 832040
print("✅ LRU缓存测试通过")
if __name__ == "__main__":
test_params()
test_return()
test_lambda()
test_decorator()
test_closure()
test_lru_cache()
print("\n🎉 第04课全部验证通过!")