python的装饰器

一、类装饰器

在Python中,装饰器是个非常强大且有用的工具,能改变或增强函数或类的行为。Python中的类装饰器就是对一个类进行装饰,以修改或增强这个类的一些行为。
普通的函数装饰器只接受一个函数,并返回一个函数,类装饰器接受一个类并返回一个类。
类装饰器的一个常见用途是提供类的一种初始化方式。以下是一个类装饰器的示例,它在类被定义时添加一个额外的方法:

def add_method(classObj):
    classObj.extra_method = lambda self: "extra method was called"
    return classObj


@add_method
class MyClass:
    def __init__(self, name):
        self.name = name


obj = MyClass("Test")
print(obj.extra_method())  # prints: extra method was called

在这个示例中,装饰器add_method添加了一个新的方法extra_method到类MyClass上。所以当我们创建MyClass的新实例并调用extra_method时,将会返回字符串"extra method was called"。
这只是类装饰器的一个简单示例,类装饰器可以用于执行各种有趣和有用的任务,如做一些预处理、后处理工作,增加新的方法或属性,甚至可以改变类的行为。

二、函数装饰器

在Python中,函数装饰器是一个非常强大的工具,它可以修改一个函数的行为。基本形式如下:

def my_decorator(func):
    def wrapper():
        # 在函数执行前做一些事
        func()
        # 在函数执行后做一些事

    return wrapper


@my_decorator
def my_function():
    pass

在这里,my_decorator就是一个装饰器。其基本思想就是,当你这样的调用一个函数:@my_decorator,你实际上是在执行 my_function = my_decorator(my_function)。
装饰器的一种常见用法是在函数执行前后插入日志代码:

def log_decorator(func):
    def wrapper(*args, **kwargs):
        print(f"Before calling {func.__name__}")
        result = func(*args, **kwargs)
        print(f"After calling {func.__name__}")
        return result

    return wrapper


@log_decorator
def say_hello():
    print("Hello")


say_hello()

在这个示例中,我们有一个log_decorator装饰器,它在函数调用前后打印一条消息。我们使用 @log_decorator 修饰 say_hello 函数,该函数的行为被修改为:在打印 "Hello" 之前和之后,分别打印 "Before calling say_hello " 和 "After calling say_hello "。

三、带参数的装饰器

Python中的装饰器可以带参数,这种装饰器也称为"参数化装饰器"。参数化装饰器可以在声明时接受额外的参数,这些参数可以用来控制装饰器的行为。
带参数的装饰器实际上是一个装饰器的工厂函数,它返回一个装饰器,然后这个装饰器去装饰目标函数。所以带参数的装饰器需要三层嵌套的函数。

以下是一个简单的带参数的装饰器例子:

def repeat(num_times):
    def decorator_repeat(func):
        def wrapper(*args, **kwargs):
            for _ in range(num_times):
                result = func(*args, **kwargs)
            return result

        return wrapper

    return decorator_repeat


# 使用
@repeat(num_times=4)
def greet(name):
    print(f"Hello {name}")


greet("World")  # 输出 "Hello World" 4次

在这个例子中,repeat(num_times=4) 会返回一个装饰器 decorator_repeat,然后 decorator_repeat 去装饰函数 greet。
这样,我们便可以控制 greet 函数被调用的次数,把次数作为参数传给装饰器 repeat。

四、装饰器链

Python 装饰器可以"链式"使用,就是说你可以同时将多个装饰器应用到一个函数上。使用装饰器链时,应用的顺序会影响结果。
装饰器在应用时,离函数最近的装饰器会被首先应用,然后依此向上应用其他的装饰器。
看一个简单的示例:

def decorator1(func):
    def wrapper1():
        print("Decorator1 before call")
        func()
        print("Decorator1 after call")

    return wrapper1


def decorator2(func):
    def wrapper2():
        print("Decorator2 before call")
        func()
        print("Decorator2 after call")

    return wrapper2


@decorator1
@decorator2
def hello():
    print("Hello")


hello()

在这个示例中,我们有两个装饰器 decorator1 和 decorator2,且都应用到了 hello 函数上。当调用 hello 函数时,会看到如下打印结果:

Decorator1 before call
Decorator2 before call
Hello
Decorator2 after call
Decorator1 after call

可以看到,先应用的装饰器是离函数更近的装饰器 decorator2,然后才是装饰器 decorator1。所以我们可以得出结论:在装饰器链中,装饰器的执行顺序是从最近的函数开始,依次向上执行。

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值