详解Python 装饰器

  • Post category:Python

当我们需要在现有的函数或类中添加一些额外的功能时,我们不希望直接修改原来的函数或类,而是需要一种方式能够在不改变原有代码的基础上扩展它的功能。因此,Python中提供了装饰器(Decorator)这种编程方式。

装饰器本质上就是一个函数,可以在运行时动态地增加功能到某个函数或类上。Python中使用 @ 符号,将一个函数或类传递给装饰器函数,进而执行装饰器的功能。

下面是Python装饰器的使用方法攻略及示例:

装饰器的基本使用

  • 创建一个简单的装饰器
def my_decorator(func):
    def wrapper():
        print("执行函数之前的操作")
        func()
        print("执行函数之后的操作")
    return wrapper

@my_decorator
def say_hello():
    print("你好")

say_hello()

在上面的代码中,我们定义了一个装饰器 my_decorator。它接收一个参数 func,用来表示需要装饰的函数。wrapper 函数是内部的函数,负责添加额外的功能。最后返回 wrapper 函数。

在下面的代码中,使用 @my_decorator 装饰函数 say_hello。当我们调用 say_hello 的时候,实际上是在执行 my_decorator 函数中的 wrapper 函数,因此可以看到输出 “执行函数之前的操作”、”你好” 和 “执行函数之后的操作”。

  • 装饰器中使用参数
def my_decorator(func):
    def wrapper(*args, **kwargs):
        print("执行函数之前的操作")
        func(*args, **kwargs)
        print("执行函数之后的操作")
    return wrapper

@my_decorator
def say_hello(name):
    print("你好,{}".format(name))

say_hello("小明")

在上面的代码中,我们定义了一个装饰器 my_decorator,并将参数 args 和 kwargs 传递给了 wrapper 函数。当使用装饰器装饰函数 say_hello 时,我们需要传递调用 say_hello 所需的参数。当我们调用 say_hello 函数时,装饰器会自动解析传入的参数,并将参数传递给原始函数。

装饰器的高级使用

  • 为装饰器增加参数
def repeat(num):
    def my_decorator(func):
        def wrapper(*args, **kwargs):
            for i in range(num):
                print("执行函数之前的操作")
                func(*args, **kwargs)
                print("执行函数之后的操作")
        return wrapper
    return my_decorator

@repeat(num=3)
def say_hello(name):
    print("你好,{}".format(name))

say_hello("小明")

在上面的代码中,我们在装饰器函数 my_decorator 外包了一层函数 repeat,将其作为一个参数传递给 my_decorator。我们可以使用 @repeat(num=3) 的方式来将装饰器装饰到函数上,并传递repeat函数所需的参数 num。当我们调用 say_hello 时,将会执行三次函数。

  • 对类进行装饰
def my_decorator(cls):
    class NewCls:
        def __init__(self, *args, **kwargs):
            self.obj = cls(*args, **kwargs)
        def __getattr__(self, name):
            print("在执行函数之前的操作")
            return getattr(self.obj, name)
    return NewCls

@my_decorator
class MyClass:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def add(self):
        return self.x + self.y

obj = MyClass(4, 5)
print(obj.add())

在上面的代码中,我们定义了一个装饰器 my_decorator。我们使用它来修饰类 MyClass,并定义了一个新的类 NewCls。在 NewCls 中,我们重写了 initgetattr 方法,将被装饰的类 MyClass 实例化,并将其作为其实例属性 self.obj。当我们调用 MyClass 的方法时,在执行函数之前,会打印 “在执行函数之前的操作”,并返回被装饰类的方法。通过对类的装饰,可以扩展类的功能,使其更加灵活和功能强大。