什么是闭包和装饰器,装饰器缺点是什么

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(面向切面编程)的核心工具。其应用场景广泛,包括日志、性能优化、权限控制等。合理使用装饰器可显著提升代码的简洁性和可维护性,但需注意参数传递、执行顺序及元信息保留等问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值