文章目录
1.闭包
Python中的闭包函数是一种特殊类型的函数,它允许内部函数访问并操作外部函数的变量,即使外部函数已经执行完毕。
1.1闭包的定义
闭包是由一个内部函数和对外部函数变量的引用组成的。
内部函数可以访问外部函数的局部变量,即使外部函数已经返回。
外部函数返回内部函数的引用,使得内部函数可以在外部函数作用域之外被调用
1.2闭包的工作原理
当外部函数被调用时,它创建了一个新的作用域,并返回内部函数。
内部函数通过作用域链访问外部函数的变量,即使外部函数已经执行完毕,这些变量仍然存在于内存中。
内部函数持有对外部函数作用域的引用,直到内部函数不再被引用,外部函数的变量才会被垃圾回收。
1.3闭包的应用场景
- 函数工厂:创建一系列具有相同行为但不同状态的函数。
- 装饰器:在不修改原函数代码的情况下增强函数功能。
- 数据封装:保护函数内的变量安全,避免全局变量的污染。
- 状态保持:在内存中维持变量状态,实现计数器等功能。
- 装饰器常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。
1.4闭包的示例
def outer_function(x):
def inner_function(y):
return x + y
return inner_function
closure = outer_function(10)
result = closure(5)
print(result) # 输出 15
在这个例子中,outer_function 返回了 inner_function,并且 inner_function 能够访问 outer_function 的变量 x。即使 outer_function 已经执行完毕,inner_function 仍然可以使用 x。
注意事项
- 闭包会使得外部函数的变量被保存在内存中,可能导致内存消耗增加。
- 不当使用闭包可能导致内存泄漏,特别是在循环中创建大量闭包时。
- 在内部函数中修改外部函数的变量时,需要使用 nonlocal 关键字声明变量。
总之,闭包函数是Python中一个强大且灵活的特性,它允许函数携带状态,并在不同的调用之间保持这些状态。通过闭包,可以实现许多高级的编程技巧和设计模式。
2.装饰器
Python装饰器是一种强大的元编程工具,允许开发者在不修改原函数代码的情况下动态增强其功能。以下是装饰器的核心概念、实现方式及实际应用场景的详细解析:
2.1装饰器的核心概念
2.11定义与原理
装饰器本质上是一个高阶函数,接受一个函数作为参数,并返回一个新的函数(通常称为wrapper)。其核心原理基于闭包,通过嵌套函数实现对原函数的包裹和功能扩展。例如:
def decorator(func):
def wrapper:
print("装饰器前操作")
func
print("装饰器后操作")
return wrapper
@decorator
def target_func:
print("原函数逻辑")
此时target_func被替换为wrapper函数,调用时会自动执行装饰器添加的逻辑。
2.12语法糖
使用@ 函数名/类名 可以实现给绑定函数/类额外功能。
@decorator语法是target_func = decorator(target_func)的简写形式,简化了装饰器的使用。
2.1.3装饰器的引导
# 将函数存储在变量中
def print_message(message):
print(f'send message:{message}')
# 变量名引用函数名
send_message = print_message
send_message('Hi, python!') # send message:Hi, python!
print(type(send_message), type(print_message)) # <class 'function'> <class 'function'>
# 相同的地址
print(id(send_message), id(print_message)) # 2664582954528 2664582954528
# 将函数作为参数传递给另外一个函数
def return_message(message):
return f'send message:{message}'
def call_message(func, message):
print(func(message))
call_message(return_message, 'Hi, python!') # send message:Hi, python!
# 函数嵌套
def func(outer_message):
def print_message(message):
print(f'print message:{message}')
return print_message(outer_message)
func('Hi, python!') # print message:Hi, python!
# 闭包
def outer():
def inner(message):
print(f'print message:{message}')
return inner
send_message = outer()
send_message('Hi, python!') # print message:Hi, python!
# 装饰器
def my_decorator(func):
def wrapper():
print('my_decorator_wrapper')
func()
return wrapper
@ my_decorator # 或 @my_decorator
def print_message():
print('Hi, python!')
print_message()
执行结果:
my_decorator_wrapper
Hi, python!
# 通过函数嵌套实现同样的功能
def my_decorator(func):
def wrapper():
print('my_decorator_wrapper')
func()
return wrapper
def print_message():
print('Hi, python!')
func = my_decorator(print_message)
func()
2.2装饰器的常见应用场景
2.2.1日志记录
通过装饰器自动记录函数调用信息(如参数、返回值),适用于调试和监控:
import logging
def log_decorator(func):
def wrapper(*args, **kwargs):
logging.info(f"调用函数 {func.__name__},参数:{args}, {kwargs}")
return func(*args, **kwargs)
return wrapper
2.2.2性能监控
统计函数执行时间,用于性能优化:
import time
def timing_decorator(func):
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
2.2.3权限校验
在Web开发中验证用户权限,避免未授权访问:
from functools import wraps
def permission_required permission):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
if user permission != permission:
raise PermissionError("无权限")
return func(*args, **kwargs)
return wrapper
return decorator
2.2.4结果缓存
使用lru_cache缓存函数结果,减少重复计算:
from functools import lru_cache
@lru_cache(maxsize=128)
def expensive Calculation(n):
# 耗时计算逻辑
2.2.5类型检查
自定义装饰器验证函数参数类型,避免运行时错误:`
def type_check(func):
def wrapper(*args, **kwargs):
for arg in args:
if not isinstance(arg, int):
raise TypeError("参数必须为整数")
return func(*args, **kwargs)
return wrapper
2.3进阶用法与注意事项
2.3.1带参数的装饰器
通过多层嵌套函数实现装饰器参数配置:
def repeat(n):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(n):
func(*args, **kwargs)
return wrapper
return decorator
@repeat(3)
def greet:
print("Hello")
2.3.2多层装饰器
装饰器按从下到上的顺序应用,但执行时按从上到下的顺序执行:
@decorator1
@decorator2
def func:
pass # 实际调用顺序为 decorator1(decorator2(func))
2.3.3保留元信息
使用functools.wraps保留原函数的名称和文档字符串,避免调试时信息丢失
。
2.4项目中的实践建议
1.代码复用
将通用逻辑(如日志、权限)封装为装饰器,减少重复代码。
2.可维护性
通过装饰器分离关注点,使核心逻辑与横切关注点(如日志、缓存)解耦。
3.性能优化
对高频调用函数添加缓存或性能监控装饰器,提升系统效率。
2.5总结
装饰器通过闭包机制实现了函数行为的动态扩展,是Python中实现AOP(面向切面编程)的核心工具。其应用场景广泛,包括日志、性能优化、权限控制等。合理使用装饰器可显著提升代码的简洁性和可维护性,但需注意参数传递、执行顺序及元信息保留等问题。