Python 装饰器

Python 装饰器

1. 装饰器是什么

装饰器是 Python 中的一种高级函数,用于在不修改原始函数代码的前提下,动态地为函数或类增加功能。它本质上是一个函数,接受另一个函数或类作为参数,并返回一个新的函数或类。

装饰器的基本语法

def decorator(func):
    def wrapper(*args, **kwargs):
        # 在调用函数之前添加额外的行为
        print("Before the function call")
        result = func(*args, **kwargs)
        # 在调用函数之后添加额外的行为
        print("After the function call")
        return result
    return wrapper

@decorator
def my_function():
    print("This is the main function")

# 调用时
my_function()

输出:

Before the function call
This is the main function
After the function call

多个装饰器

多个装饰器可以叠加使用,每个装饰器会按顺序应用:

@decorator1
@decorator2
def my_function():
    pass

装饰器的应用顺序是从内到外:首先应用 @decorator2,然后是 @decorator1

自定义装饰器

可以根据需要自定义装饰器,为函数增加日志记录、权限检查、缓存等功能。

def custom_decorator(func):
    def wrapper(*args, **kwargs):
        print("Custom behavior before the function")
        return func(*args, **kwargs)
    return wrapper

@custom_decorator
def example():
    print("Original function behavior")

2. 常见的装饰器

@property

@property 装饰器将类的方法转化为属性,可以通过点操作符访问,而不是调用它作为一个函数。

class MyClass:
    def __init__(self, value):
        self._value = value

    @property
    def value(self):
        return self._value

obj = MyClass(10)
print(obj.value)  # 直接访问属性,不用加括号

@staticmethod@classmethod

  • @staticmethod:定义静态方法,不能访问类的实例或类本身。
  • @classmethod:定义类方法,第一个参数是类本身 cls,可以访问类的属性和方法。
class MyClass:
    @staticmethod
    def static_method():
        print("This is a static method")

    @classmethod
    def class_method(cls):
        print("This is a class method")

MyClass.static_method()
MyClass.class_method()

3. @contextmanager

@contextmanager 是 Python 标准库中的 contextlib 模块提供的一个装饰器,用于简化上下文管理器的编写,使得我们可以通过 with 语句安全地管理资源(如文件、数据库连接等),确保资源的正确获取与释放。

@contextmanager 的使用

通过 @contextmanager,可以使用简单的生成器函数代替编写完整的上下文管理类。

from contextlib import contextmanager

@contextmanager
def open_file(file_name):
    f = open(file_name, 'r')
    try:
        yield f  # 提供上下文管理的资源
    finally:
        f.close()  # 确保在退出时关闭文件

# 使用上下文管理器
with open_file('test.txt') as f:
    content = f.read()
    print(content)

with 语句

with 语句是 Python 中管理资源的常用方式,它能够确保在块结束时自动释放资源,不论是否发生异常。

with open('file.txt', 'r') as f:
    data = f.read()

with 语句背后的机制是对象实现了上下文管理协议,即实现了 __enter____exit__ 方法。

@contextmanager 的内部原理

@contextmanager 是通过生成器的 yield 语句来切分上下文进入和退出的时机。在 yield 之前的部分相当于 __enter__,而在 yield 之后的部分相当于 __exit__,用于管理资源的释放。

自定义上下文管理器的完整类实现

除了 @contextmanager,你还可以通过类的 __enter____exit__ 方法来实现上下文管理器。

class MyContextManager:
    def __enter__(self):
        print("Entering the context")
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("Exiting the context")

with MyContextManager() as manager:
    print("Inside the with block")

@contextmanager 与对象初始化的区别

需要注意的是,@contextmanager 仅用于创建上下文管理器,与对象的初始化过程(即类的 __init__ 方法)无关。对象的初始化通常不涉及资源管理,因此不需要使用 @contextmanager

4. 装饰器与上下文管理器的应用场景

  • 装饰器:适用于增强函数功能、添加日志记录、权限控制、缓存等场景。
  • 上下文管理器:适用于需要明确资源管理的场景,如文件、数据库连接的打开与关闭。
posted @ 2024-10-11 15:08  ganph  阅读(301)  评论(0)    收藏  举报