Python 函数
目录
函数基础
定义和调用函数
# 定义函数
def greet():
print("Hello, World!")
# 调用函数
greet() # Hello, World!
带参数的函数
def greet(name):
print(f"Hello, {name}!")
greet("张三") # Hello, 张三!
greet("李四") # Hello, 李四!
文档字符串(Docstring)
def add(a, b):
"""
计算两个数的和
参数:
a: 第一个数
b: 第二个数
返回:
两个数的和
"""
return a + b
# 查看文档
print(add.__doc__)
help(add)
函数的优点
# ❌ 不推荐:重复代码
print("=== 用户1信息 ===")
print("姓名: 张三")
print("年龄: 25")
print("城市: 北京")
print("=== 用户2信息 ===")
print("姓名: 李四")
print("年龄: 30")
print("城市: 上海")
# ✅ 推荐:使用函数
def show_user_info(name, age, city):
print(f"=== {name}信息 ===")
print(f"姓名: {name}")
print(f"年龄: {age}")
print(f"城市: {city}")
show_user_info("张三", 25, "北京")
show_user_info("李四", 30, "上海")
参数详解
位置参数
def introduce(name, age, city):
print(f"我叫{name},今年{age}岁,来自{city}")
# 必须按顺序传递
introduce("张三", 25, "北京")
# introduce(25, "张三", "北京") # 逻辑错误
默认参数
def greet(name, greeting="你好"):
print(f"{greeting}, {name}!")
greet("张三") # 你好, 张三!
greet("李四", "早上好") # 早上好, 李四!
# 注意:默认参数必须是不可变对象
def add_item(item, items=None):
if items is None:
items = []
items.append(item)
return items
print(add_item("苹果")) # ['苹果']
print(add_item("香蕉")) # ['香蕉'](不会累积)
关键字参数
def create_profile(name, age, city, job):
print(f"姓名: {name}")
print(f"年龄: {age}")
print(f"城市: {city}")
print(f"职业: {job}")
# 使用关键字参数,可以不按顺序
create_profile(name="张三", age=25, city="北京", job="工程师")
create_profile(job="设计师", name="李四", age=28, city="上海")
# 混合使用
create_profile("王五", 30, job="教师", city="广州")
可变位置参数 *args
def sum_all(*args):
"""接受任意数量的位置参数"""
total = 0
for num in args:
total += num
return total
print(sum_all(1, 2, 3)) # 6
print(sum_all(1, 2, 3, 4, 5)) # 15
print(sum_all()) # 0
# args 是一个元组
def show_args(*args):
print(f"类型: {type(args)}")
print(f"内容: {args}")
show_args(1, 2, 3)
# 类型: <class 'tuple'>
# 内容: (1, 2, 3)
可变关键字参数 **kwargs
def create_user(**kwargs):
"""接受任意数量的关键字参数"""
user = {}
for key, value in kwargs.items():
user[key] = value
return user
user = create_user(name="张三", age=25, city="北京")
print(user) # {'name': '张三', 'age': 25, 'city': '北京'}
# kwargs 是一个字典
def show_kwargs(**kwargs):
print(f"类型: {type(kwargs)}")
print(f"内容: {kwargs}")
show_kwargs(name="李四", age=30)
# 类型: <class 'dict'>
# 内容: {'name': '李四', 'age': 30}
组合使用所有参数类型
def complex_function(positional, default="默认值", *args, keyword_only, **kwargs):
"""
演示所有参数类型的组合
参数顺序必须是:
1. 位置参数
2. 默认参数
3. *args
4. 关键字-only 参数
5. **kwargs
"""
print(f"位置参数: {positional}")
print(f"默认参数: {default}")
print(f"可变位置参数: {args}")
print(f"关键字-only参数: {keyword_only}")
print(f"可变关键字参数: {kwargs}")
complex_function("必传", "自定义", 1, 2, 3, keyword_only="必须", extra1="额外1", extra2="额外2")
参数解包
# 列表/元组解包
def add(a, b, c):
return a + b + c
numbers = [1, 2, 3]
result = add(*numbers) # 等价于 add(1, 2, 3)
print(result) # 6
# 字典解包
def greet(name, age):
print(f"{name}, {age}岁")
info = {"name": "张三", "age": 25}
greet(**info) # 等价于 greet(name="张三", age=25)
返回值
基本返回
def add(a, b):
return a + b
result = add(3, 5)
print(result) # 8
返回多个值
def get_user_info():
name = "张三"
age = 25
city = "北京"
return name, age, city # 返回元组
# 解包接收
name, age, city = get_user_info()
print(f"{name}, {age}岁, 来自{city}")
# 或者作为元组接收
info = get_user_info()
print(info) # ('张三', 25, '北京')
返回不同类型
def divide(a, b):
if b == 0:
return None, "除数不能为零"
return a / b, "成功"
result, message = divide(10, 2)
print(f"结果: {result}, 状态: {message}")
result, message = divide(10, 0)
print(f"结果: {result}, 状态: {message}")
没有返回值
def greet(name):
print(f"Hello, {name}!")
result = greet("张三")
print(result) # None(没有return语句,默认返回None)
early return(提前返回)
def check_age(age):
if age < 0:
return "无效年龄"
if age < 18:
return "未成年人"
if age < 60:
return "成年人"
return "老年人"
print(check_age(-1)) # 无效年龄
print(check_age(15)) # 未成年人
print(check_age(25)) # 成年人
print(check_age(65)) # 老年人
变量作用域
局部变量和全局变量
global_var = "全局变量"
def test_scope():
local_var = "局部变量"
print(global_var) # 可以访问全局变量
print(local_var) # 可以访问局部变量
test_scope()
# print(local_var) # NameError: 无法在函数外访问局部变量
global 关键字
count = 0
def increment():
global count # 声明使用全局变量
count += 1
increment()
print(count) # 1
increment()
print(count) # 2
nonlocal 关键字
def outer():
x = 10
def inner():
nonlocal x # 声明使用外层函数的变量
x += 5
print(f"inner: {x}")
inner()
print(f"outer: {x}")
outer()
# inner: 15
# outer: 15
LEGB 规则
Python 查找变量的顺序:
- 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 apply_operation(func, a, b):
"""接受一个函数作为参数"""
return func(a, b)
def add(a, b):
return a + b
def multiply(a, b):
return a * b
print(apply_operation(add, 3, 5)) # 8
print(apply_operation(multiply, 3, 5)) # 15
函数作为返回值
def create_multiplier(factor):
"""返回一个函数"""
def multiplier(number):
return number * factor
return multiplier
double = create_multiplier(2)
triple = create_multiplier(3)
print(double(5)) # 10
print(triple(5)) # 15
map() 函数
numbers = [1, 2, 3, 4, 5]
# 使用 map
squares = list(map(lambda x: x**2, numbers))
print(squares) # [1, 4, 9, 16, 25]
# 等价于列表推导式
squares = [x**2 for x in numbers]
filter() 函数
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# 使用 filter
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens) # [2, 4, 6, 8, 10]
# 等价于列表推导式
evens = [x for x in numbers if x % 2 == 0]
reduce() 函数
from functools import reduce
numbers = [1, 2, 3, 4, 5]
# 累加
total = reduce(lambda x, y: x + y, numbers)
print(total) # 15
# 累乘
product = reduce(lambda x, y: x * y, numbers)
print(product) # 120
# 找最大值
max_value = reduce(lambda x, y: x if x > y else y, numbers)
print(max_value) # 5
匿名函数 lambda
基本语法
# 传统函数
def add(a, b):
return a + b
# lambda 函数
add = lambda a, b: a + b
print(add(3, 5)) # 8
常见用法
# 排序
students = [
{"name": "张三", "score": 85},
{"name": "李四", "score": 92},
{"name": "王五", "score": 78}
]
# 按分数排序
sorted_students = sorted(students, key=lambda s: s["score"])
for s in sorted_students:
print(f"{s['name']}: {s['score']}")
# 多条件排序
sorted_students = sorted(students, key=lambda s: (-s["score"], s["name"]))
结合高阶函数
numbers = [1, 2, 3, 4, 5]
# map + lambda
squares = list(map(lambda x: x**2, numbers))
print(squares) # [1, 4, 9, 16, 25]
# filter + lambda
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens) # [2, 4]
# sorted + lambda
words = ["banana", "apple", "cherry", "date"]
sorted_words = sorted(words, key=lambda w: len(w))
print(sorted_words) # ['date', 'apple', 'banana', 'cherry']
lambda 的限制
# ✅ lambda 只能是表达式,不能有语句
add = lambda a, b: a + b
# ❌ 不能有赋值语句
# func = lambda x: y = x + 1 # SyntaxError
# ❌ 不能有循环
# func = lambda x: for i in range(x): print(i) # SyntaxError
# ❌ 不能有异常处理
# func = lambda x: try: int(x) except: 0 # SyntaxError
装饰器
装饰器基础
def my_decorator(func):
def wrapper():
print("函数执行前")
func()
print("函数执行后")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
# 输出:
# 函数执行前
# Hello!
# 函数执行后
带参数的装饰器
def timer_decorator(func):
import time
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"{func.__name__} 执行时间: {end_time - start_time:.4f}秒")
return result
return wrapper
@timer_decorator
def slow_function():
import time
time.sleep(1)
return "完成"
result = slow_function()
print(result)
保留函数元信息
from functools import wraps
def my_decorator(func):
@wraps(func) # 保留原函数的元信息
def wrapper(*args, **kwargs):
"""wrapper 的文档"""
return func(*args, **kwargs)
return wrapper
@my_decorator
def greet(name):
"""greet 函数的文档"""
print(f"Hello, {name}!")
print(greet.__name__) # greet(而不是 wrapper)
print(greet.__doc__) # greet 函数的文档
实用装饰器示例
from functools import wraps
# 日志装饰器
def logger(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
# 缓存装饰器
def cache(func):
cache_dict = {}
@wraps(func)
def wrapper(*args):
if args not in cache_dict:
cache_dict[args] = func(*args)
return cache_dict[args]
wrapper.cache = cache_dict
return wrapper
# 权限检查装饰器
def require_login(func):
@wraps(func)
def wrapper(user, *args, **kwargs):
if not user.get("logged_in"):
raise PermissionError("需要登录")
return func(user, *args, **kwargs)
return wrapper
# 使用装饰器
@logger
@cache
def fibonacci(n):
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)
print(fibonacci(10)) # 55
带参数的装饰器
def repeat(times):
def decorator(func):
@wraps(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("张三")
# 输出三次: Hello, 张三!
生成器
生成器函数
def count_up_to(n):
"""生成器函数:使用 yield"""
i = 1
while i <= n:
yield i
i += 1
# 创建生成器对象
counter = count_up_to(5)
# 逐个获取值
print(next(counter)) # 1
print(next(counter)) # 2
print(next(counter)) # 3
# 遍历剩余的值
for num in counter:
print(num) # 4, 5
生成器表达式
# 列表推导式 - 立即创建完整列表
squares_list = [x**2 for x in range(1000000)]
# 生成器表达式 - 惰性求值,节省内存
squares_gen = (x**2 for x in range(1000000))
print(type(squares_list)) # <class 'list'>
print(type(squares_gen)) # <class 'generator'>
# 逐个获取
print(next(squares_gen)) # 0
print(next(squares_gen)) # 1
生成器的优势
import sys
# 列表 - 占用大量内存
numbers_list = [x for x in range(1000000)]
print(f"列表大小: {sys.getsizeof(numbers_list)} bytes")
# 生成器 - 占用很少内存
numbers_gen = (x for x in range(1000000))
print(f"生成器大小: {sys.getsizeof(numbers_gen)} bytes")
# 处理大文件
def read_large_file(filename):
with open(filename, 'r') as f:
for line in f:
yield line.strip()
# 逐行处理,不需要一次性加载整个文件
for line in read_large_file("large_file.txt"):
process(line)
send() 和 close()
def coroutine():
print("协程启动")
while True:
value = yield
print(f"收到: {value}")
coro = coroutine()
next(coro) # 启动协程
coro.send("Hello") # 收到: Hello
coro.send("World") # 收到: World
coro.close() # 关闭协程
递归函数
基本概念
def factorial(n):
"""计算阶乘"""
if n == 0 or n == 1:
return 1
return n * factorial(n - 1)
print(factorial(5)) # 120
# 5! = 5 × 4 × 3 × 2 × 1 = 120
递归三要素
- 基准情况(停止条件)
- 递归情况(调用自身)
- 向基准情况靠近
def fibonacci(n):
"""斐波那契数列"""
# 基准情况
if n <= 0:
return 0
if n == 1:
return 1
# 递归情况
return fibonacci(n - 1) + fibonacci(n - 2)
# 打印前10个斐波那契数
for i in range(10):
print(fibonacci(i), end=" ")
# 0 1 1 2 3 5 8 13 21 34
递归优化
# ❌ 效率低:大量重复计算
def fibonacci_slow(n):
if n <= 1:
return n
return fibonacci_slow(n-1) + fibonacci_slow(n-2)
# ✅ 使用缓存优化
from functools import lru_cache
@lru_cache(maxsize=None)
def fibonacci_fast(n):
if n <= 1:
return n
return fibonacci_fast(n-1) + fibonacci_fast(n-2)
# ✅ 或使用迭代
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
递归示例
# 二分查找
def binary_search(arr, target, low=0, high=None):
if high is None:
high = len(arr) - 1
if low > high:
return -1
mid = (low + high) // 2
if arr[mid] == target:
return mid
elif arr[mid] > target:
return binary_search(arr, target, low, mid - 1)
else:
return binary_search(arr, target, mid + 1, high)
numbers = [1, 3, 5, 7, 9, 11, 13, 15]
print(binary_search(numbers, 7)) # 3
print(binary_search(numbers, 6)) # -1
# 快速排序
def quick_sort(arr):
if len(arr) <= 1:
return arr
pivot = arr[len(arr) // 2]
left = [x for x in arr if x < pivot]
middle = [x for x in arr if x == pivot]
right = [x for x in arr if x > pivot]
return quick_sort(left) + middle + quick_sort(right)
print(quick_sort([3, 6, 8, 10, 1, 2, 1]))
# [1, 1, 2, 3, 6, 8, 10]
递归深度限制
import sys
# 查看递归深度限制
print(sys.getrecursionlimit()) # 通常是 1000
# 修改递归深度限制(谨慎使用)
sys.setrecursionlimit(2000)
# ❌ 递归过深会导致栈溢出
# def infinite_recursion(n):
# return infinite_recursion(n + 1)
# infinite_recursion(0) # RecursionError
综合实战
实战1: 函数式数据处理管道
from functools import reduce
class DataPipeline:
"""函数式数据处理管道"""
def __init__(self, data):
self.data = list(data)
def filter(self, func):
"""过滤数据"""
self.data = list(filter(func, self.data))
return self
def map(self, func):
"""转换数据"""
self.data = list(map(func, self.data))
return self
def sort(self, key=None, reverse=False):
"""排序数据"""
self.data = sorted(self.data, key=key, reverse=reverse)
return self
def reduce(self, func, initial=None):
"""归约数据"""
if initial is None:
return reduce(func, self.data)
return reduce(func, self.data, initial)
def take(self, n):
"""取前n个"""
self.data = self.data[:n]
return self
def skip(self, n):
"""跳过前n个"""
self.data = self.data[n:]
return self
def result(self):
"""获取结果"""
return self.data
# 使用示例
numbers = range(1, 101)
result = (DataPipeline(numbers)
.filter(lambda x: x % 2 == 0) # 只要偶数
.map(lambda x: x ** 2) # 平方
.filter(lambda x: x > 100) # 大于100
.sort(reverse=True) # 降序
.take(10) # 前10个
.result())
print("前10个大于100的偶数平方(降序):")
print(result)
# 计算总和
total = (DataPipeline(range(1, 101))
.filter(lambda x: x % 3 == 0 or x % 5 == 0)
.reduce(lambda x, y: x + y))
print(f"\n1-100中3或5的倍数之和: {total}")
实战2: 缓存系统
import time
from functools import wraps
class CacheSystem:
"""简易缓存系统"""
def __init__(self, max_size=100, ttl=300):
self.cache = {}
self.max_size = max_size
self.ttl = ttl # 生存时间(秒)
def cached(self, func):
"""缓存装饰器"""
@wraps(func)
def wrapper(*args, **kwargs):
# 创建缓存键
key = (func.__name__, args, tuple(sorted(kwargs.items())))
# 检查缓存
if key in self.cache:
result, timestamp = self.cache[key]
if time.time() - timestamp < self.ttl:
print(f"缓存命中: {func.__name__}")
return result
else:
del self.cache[key]
# 执行函数
print(f"执行函数: {func.__name__}")
result = func(*args, **kwargs)
# 存储缓存
if len(self.cache) >= self.max_size:
# 删除最旧的缓存
oldest_key = min(self.cache, key=lambda k: self.cache[k][1])
del self.cache[oldest_key]
self.cache[key] = (result, time.time())
return result
wrapper.clear_cache = lambda: self.cache.clear()
wrapper.cache_info = lambda: len(self.cache)
return wrapper
# 使用示例
cache = CacheSystem(max_size=50, ttl=60)
@cache.cached
def expensive_computation(n):
"""模拟耗时计算"""
time.sleep(2)
return sum(i ** 2 for i in range(n))
# 第一次调用(慢)
start = time.time()
result1 = expensive_computation(1000)
print(f"结果: {result1}, 耗时: {time.time() - start:.2f}秒")
# 第二次调用(快,从缓存)
start = time.time()
result2 = expensive_computation(1000)
print(f"结果: {result2}, 耗时: {time.time() - start:.2f}秒")
print(f"缓存大小: {expensive_computation.cache_info()}")
实战3: 插件系统
class PluginSystem:
"""插件系统"""
def __init__(self):
self.plugins = {}
def register(self, name=None):
"""注册插件装饰器"""
def decorator(func):
plugin_name = name or func.__name__
self.plugins[plugin_name] = func
print(f"插件 '{plugin_name}' 已注册")
return func
return decorator
def execute(self, name, *args, **kwargs):
"""执行插件"""
if name not in self.plugins:
raise ValueError(f"插件 '{name}' 未找到")
plugin = self.plugins[name]
print(f"执行插件: {name}")
return plugin(*args, **kwargs)
def list_plugins(self):
"""列出所有插件"""
return list(self.plugins.keys())
# 创建插件系统
plugins = PluginSystem()
# 注册插件
@plugins.register()
def greet(name):
return f"你好, {name}!"
@plugins.register()
def add(a, b):
return a + b
@plugins.register(name="multiply")
def mul(a, b):
return a * b
@plugins.register()
def uppercase(text):
return text.upper()
# 使用插件
print(plugins.execute("greet", "张三"))
print(plugins.execute("add", 10, 20))
print(plugins.execute("multiply", 5, 6))
print(plugins.execute("uppercase", "hello world"))
print(f"\n已注册插件: {plugins.list_plugins()}")
实战4: 验证器系统
from functools import wraps
class Validator:
"""参数验证器"""
@staticmethod
def type_check(**type_specs):
"""类型检查装饰器"""
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
# 检查位置参数
for i, (param_name, expected_type) in enumerate(type_specs.items()):
if i < len(args):
if not isinstance(args[i], expected_type):
raise TypeError(
f"参数 '{param_name}' 期望类型 {expected_type.__name__}, "
f"实际类型 {type(args[i]).__name__}"
)
# 检查关键字参数
for param_name, value in kwargs.items():
if param_name in type_specs:
expected_type = type_specs[param_name]
if not isinstance(value, expected_type):
raise TypeError(
f"参数 '{param_name}' 期望类型 {expected_type.__name__}, "
f"实际类型 {type(value).__name__}"
)
return func(*args, **kwargs)
return wrapper
return decorator
@staticmethod
def range_check(param_name, min_val=None, max_val=None):
"""范围检查装饰器"""
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
# 获取参数值
sig = func.__code__.co_varnames
if param_name in sig:
idx = sig.index(param_name)
if idx < len(args):
value = args[idx]
elif param_name in kwargs:
value = kwargs[param_name]
else:
return func(*args, **kwargs)
# 检查范围
if min_val is not None and value < min_val:
raise ValueError(f"'{param_name}' 不能小于 {min_val}")
if max_val is not None and value > max_val:
raise ValueError(f"'{param_name}' 不能大于 {max_val}")
return func(*args, **kwargs)
return wrapper
return decorator
@staticmethod
def not_empty(param_name):
"""非空检查装饰器"""
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
sig = func.__code__.co_varnames
if param_name in sig:
idx = sig.index(param_name)
if idx < len(args):
value = args[idx]
elif param_name in kwargs:
value = kwargs[param_name]
else:
return func(*args, **kwargs)
if not value:
raise ValueError(f"'{param_name}' 不能为空")
return func(*args, **kwargs)
return wrapper
return decorator
# 使用验证器
validator = Validator()
@validator.type_check(name=str, age=int, score=float)
@validator.range_check("age", min_val=0, max_val=150)
@validator.range_check("score", min_val=0, max_val=100)
@validator.not_empty("name")
def create_student(name, age, score):
"""创建学生记录"""
return {
"name": name,
"age": age,
"score": score
}
# 正常调用
student = create_student("张三", 20, 85.5)
print(f"学生创建成功: {student}")
# 错误调用
try:
create_student("", 20, 85.5) # 名字为空
except ValueError as e:
print(f"错误: {e}")
try:
create_student("李四", 200, 85.5) # 年龄超出范围
except ValueError as e:
print(f"错误: {e}")
try:
create_student("王五", "二十", 85.5) # 类型错误
except TypeError as e:
print(f"错误: {e}")
实战5: 事件系统
from collections import defaultdict
class EventEmitter:
"""事件发射器"""
def __init__(self):
self.listeners = defaultdict(list)
def on(self, event_name):
"""注册事件监听器"""
def decorator(func):
self.listeners[event_name].append(func)
return func
return decorator
def emit(self, event_name, *args, **kwargs):
"""触发事件"""
if event_name not in self.listeners:
return
results = []
for listener in self.listeners[event_name]:
try:
result = listener(*args, **kwargs)
results.append(result)
except Exception as e:
print(f"监听器错误: {e}")
return results
def off(self, event_name, func=None):
"""移除监听器"""
if func:
self.listeners[event_name].remove(func)
else:
self.listeners[event_name].clear()
# 使用示例
events = EventEmitter()
@events.on("user_login")
def log_login(username):
print(f"[日志] 用户 {username} 登录")
@events.on("user_login")
def send_welcome_email(username):
print(f"[邮件] 发送欢迎邮件给 {username}")
@events.on("user_logout")
def log_logout(username):
print(f"[日志] 用户 {username} 登出")
@events.on("order_created")
def process_order(order_id, amount):
print(f"[订单] 处理订单 {order_id}, 金额: ¥{amount}")
return "订单处理完成"
# 触发事件
print("=== 用户登录 ===")
events.emit("user_login", "张三")
print("\n=== 创建订单 ===")
results = events.emit("order_created", "ORD001", 299.99)
print(f"结果: {results}")
print("\n=== 用户登出 ===")
events.emit("user_logout", "张三")
常见错误与注意事项
1. 可变默认参数陷阱
# ❌ 危险:可变对象作为默认参数
def append_to(element, lst=[]):
lst.append(element)
return lst
print(append_to(1)) # [1]
print(append_to(2)) # [1, 2](不是预期的 [2])
# ✅ 正确:使用 None 作为默认值
def append_to_safe(element, lst=None):
if lst is None:
lst = []
lst.append(element)
return lst
print(append_to_safe(1)) # [1]
print(append_to_safe(2)) # [2]
2. 闭包中的变量捕获
# ❌ 陷阱:延迟绑定
functions = []
for i in range(5):
functions.append(lambda: i)
print([f() for f in functions]) # [4, 4, 4, 4, 4](都是4)
# ✅ 正确:使用默认参数捕获当前值
functions = []
for i in range(5):
functions.append(lambda x=i: x)
print([f() for f in functions]) # [0, 1, 2, 3, 4]
3. 递归深度限制
import sys
# ❌ 可能导致栈溢出
def deep_recursion(n):
if n == 0:
return 0
return deep_recursion(n - 1)
# deep_recursion(2000) # RecursionError
# ✅ 使用迭代替代
def iterative_solution(n):
result = 0
for i in range(n):
result += i
return result
4. 忘记返回值
# ❌ 忘记 return
def add(a, b):
result = a + b
# 忘记 return result
print(add(1, 2)) # None
# ✅ 确保有返回值
def add(a, b):
return a + b
5. 全局变量滥用
# ❌ 不推荐:依赖全局变量
count = 0
def increment():
global count
count += 1
# ✅ 推荐:使用类或返回值
class Counter:
def __init__(self):
self.count = 0
def increment(self):
self.count += 1
return self.count
小结
| 概念 | 说明 | 使用场景 |
|---|---|---|
| 基础函数 | def 定义,return 返回 | 代码复用 |
| 参数类型 | 位置、默认、*args、**kwargs | 灵活接口设计 |
| 作用域 | Local, Enclosing, Global, Built-in | 变量管理 |
| 高阶函数 | 函数作为参数或返回值 | 函数式编程 |
| Lambda | 匿名函数 | 简单回调、排序 |
| 装饰器 | 增强函数功能 | 日志、缓存、权限 |
| 生成器 | yield 惰性求值 | 大数据处理 |
| 递归 | 函数调用自身 | 分治算法 |
核心要点:
- 函数是代码复用的基本单位
- 合理使用参数类型提高灵活性
- 理解作用域避免变量冲突
- 装饰器是强大的代码增强工具
- 生成器适合处理大数据流
- 递归要确保有终止条件
- 避免可变默认参数陷阱
掌握函数是成为 Python 高手的关键!