Python装饰器

程序员卷不动了 2023-03-15 PM 377℃ 0条

Python 装饰器是一种编程模式,用于修改或扩展函数或类的行为,而不需要修改它们的源代码。Python 装饰器通常使用 "@" 符号定义,并在函数或类声明的前面使用。

使用装饰器,您可以通过将装饰器函数或者装饰器类应用到函数或类上,改变它们的行为。常用的一些 Python 装饰器包括:缓存、日志、授权、计时和调试等。

下面是一个使用装饰器修改函数行为的简单示例:

 def my_decorator(func):
    def wrapper():
        print("before")
        func()
        print("after")
    return wrapper

@my_decorator
def hello():
    print("Hello, World!")

hello()

在上例中,my_decorator 是一个装饰器函数,用于在函数调用前后打印一些内容。装饰器函数接收一个函数作为参数,然后返回一个新的函数 wrapper,该函数用来调用原始函数并执行操作。

通过在 hello 函数定义前使用 @my_decorator,我们将装饰器应用到了该函数上。这样,每次调用该函数时,都会首先打印 "before",然后调用 hello 函数,并打印 "after"。

输出结果如下:

 before
Hello, World!
after

除了使用函数作为装饰器外,Python 还支持使用类作为装饰器。使用类作为装饰器时需要实现 __call__ 方法,该方法接收函数作为参数,并返回一个新的函数。

下面是一个使用类作为装饰器的示例:

 class MyDecorator:
    def __init__(self, func):
        self._func = func
        
    def __call__(self):
        print("before")
        self._func()
        print("after")

@MyDecorator
def hello():
    print("Hello, World!")
    
hello()

在上述示例中,我们定义了一个名为 MyDecorator 的装饰器类。该类定义了两个方法: __init____call____init__ 方法用于初始化装饰器类,而 __call__ 方法用于在调用被装饰函数之前和之后执行操作。

与函数装饰器类似,我们可以使用 @MyDecorator 应用装饰器类到函数上。每次调用该函数时,都会首先打印 "before",然后调用 hello 函数,并打印 "after"。

输出结果如下:

before
Hello, World!
after

Python 装饰器非常有用,因为它们可以在不修改现有代码的情况下改变函数或类的行为。Python 标准库以及许多流行的框架都使用了装饰器来提供各种支持,包括缓存、并发执行、验证和日志等。

Python 装饰器的细节和高级用法。

装饰器链

Python 装饰器可以像管道一样连接起来,形成一个“装饰器链”。例如:

def make_bold(func):
    def wrapper():
        return "<b>" + func() + "</b>"
    return wrapper

def make_italic(func):
    def wrapper():
        return "<i>" + func() + "</i>"
    return wrapper

@make_bold
@make_italic
def hello():
    return "Hello, World!"

print(hello())

在上述示例中,我们定义了两个装饰器 make_boldmake_italic,它们分别用于添加 HTML 的加粗(bold)和斜体(italic)标签。

然后,在 hello 函数定义前使用了两个装饰器 @make_bold@make_italic,这意味着 hello 函数将首先被 make_bold 装饰器包裹,然后再由 make_italic 装饰器包裹。因此,在调用 hello 函数时,会首先添加斜体标签,然后再添加加粗标签,最终输出结果为:

<b><i>Hello, World!</i></b>

装饰器带参数

装饰器可以使用参数,这样可以让它们更加灵活。如果希望在运行时根据一些条件调整装饰器行为,那么这是非常有用的。

下面是一个带参数的装饰器示例:

def my_decorator(str_arg):
    def decorate(func):
        def wrapper():
            print("doing something before " + str_arg)
            func()
            print("doing something after " + str_arg)
        return wrapper
    return decorate

@my_decorator("decorated string")
def hello():
    print("Hello, World!")
    
hello()

在上例中,my_decorator 函数以参数形式接收一个字符串,然后返回另一个函数 decoratedecorate 函数以函数作为参数,并返回新的 wrapper 函数。在 wrapper 函数中,我们使用在调用被装饰函数之前和之后打印字符串。

我们可以通过向装饰器传递不同的字符串参数来更改装饰器行为。

因此,我们通过在装饰器名称 @my_decorator 后面添加字符串参数,将该字符串参数传递到装饰器中。

输出结果如下:

doing something before decorated string
Hello, World!
doing something after decorated string

带有状态的装饰器

装饰器本身也可以具有状态,这意味着它们可以跟踪内部变量的值。

下面是一个带有状态的装饰器示例:

def count_decorator(func):
    def wrapper():
        wrapper.count += 1
        func()
        print("Count = ", wrapper.count)
    wrapper.count = 0
    return wrapper

@count_decorator
def hello():
    print("Hello, World!")

hello()
hello()
hello()

在上例中,通过在 wrapper 函数上创建一个名称为 count 的属性来为装饰器添加状态。在每次调用被装饰的函数时,该属性将自增,值将传递给被打印到控制台的输出字符串。

当我们调用 hello 函数时,我们实际上调用了 wrapper 函数。每次调用 wrapper 函数会增加一个计数

非特殊说明,本博所有文章均为博主原创。

上一篇 Python异常处理
下一篇 Python生成器

评论啦~