你真的了解python装饰器么

合理使用装饰器可以简化开发,并且使得代码更加清晰。下面我们分别介绍两种装饰器,不带参数的装饰器和带参数的装饰器。

(推荐教程:Python入门教程)

一、不带参数的装饰器

我们用一个实际的例子来引入装饰器的概念,比如我们现在有一个方法A(),然后我们需要在方法A()执行之前在终端打印"function is running",这时候我们可以在方法A()的开始部分加上下面的代码:

print("function is running")

但是如果我们不想修改方法A()的代码,也可以重新写一个方法decorator(),然后把A()作为入参,代码如下:

def decorator(fun):
    @functools.wraps(fun)
    def wrapper(*args, **kwargs):
        print("Method is running")
        return fun()
    return wrapper

python中的方法可以作为参数传入另一个方法,所以当我们执行decorator(A)的时候,返回的是一个方法,这个方法的本质是先执行print语句,然后再执行A()。

但是这样我们的调用代码就需要进行修改,也就是说之前调用方法A(),现在的写法是调用decorator(A)(),为了不影响调用的代码,我们使用python的语法糖改造方法A()的代码。

@decorator
def A():
    # do something

实际上只是在A()的前面加上一行@decorator,这样在我们的调用代码就不需要改变了。

装饰器中的@functools.wraps(fun)是为了保证返回的方法__name__属性和入参方法fun的__name__属性相同。

二、带入参的装饰器

在上面不带参数的装饰器中,我们实现了在执行方法A()之前打印一行固定的字符串,如果我们想要打印不同的字符串就需要用带参数的装饰器。实际上就是在不带参数的装饰器上再封装一层即可,代码如下:

def decorator_par(name):
    def decorator(fun):
        @functools.wraps(fun)
        def wrapper(*args, **kwargs):
            print("Method {} is running".format(name))
            return fun()
        return wrapper
    return decorator

这样我们就可以在使用装饰器的时候设置参数name,实现打印不同的信息。完整的代码如下:

import functools
 
def decorator_par(name):
    def decorator(fun):
        @functools.wraps(fun)
        def wrapper(*args, **kwargs):
            print("Method {} is running".format(name))
            return fun()
        return wrapper
    return decorator
 
@decorator_par("A")
def A():
    print("I am A")
 
@decorator_par("B")
def B():
    print("I am B")
 
A()
B()

执行输出为:

Method A is running
I am A
Method B is running
I am B

可以看到我们在不改变方法调用代码的情况下,实现了在该方法之前打印特定的信息。

以上就是装饰器的两种实现示例,实际开发中也可以将多个装饰器进行嵌套,可以实现更加复杂的需求。

来源:PY学习网:原文地址:https://www.py.cn/article.html

hmoban主题是根据ripro二开的主题,极致后台体验,无插件,集成会员系统
自学咖网 » 你真的了解python装饰器么