装饰器

前言:

装饰器的作用是什么?直白了说就是给一个方法或者类,在其原有的功能上添加新的功能。

 

一、闭包

概念:在一个内部函数中,对外部作用域的变量进行引用,(并且一般外部函数的返回值为内部函数),那么内部函数就被认为是闭包。

来看一个例子:

def outer(x):
    def inner(y):
        sum_t = x + y
        return sum_t
    return inner


o = outer(3)
result = o(4)
print(result)

分析:

1.outer函数与inner函数嵌套。

2.内部函数引用了外部作用域的变量x。

3.外部函数返回了内部函数名(返回内部函数的引用,是python的特色之一)。

当调用了外部函数outer之后,获得的是内部函数的引用,然后调用内部函数(使用括号),即可执行内部函数的代码。

 

二、装饰器

要了解装饰器,必须先了解闭包,因为二者有着一定的联系。

def login(func):
    def wrapper():
        print("this is wrapper")

        func()

    return wrapper


@login
def check_in():
    print("this is check_in")


check_in()

执行结果:

this is wrapper
this is check_in

我们可以看到,当check_in函数杯login装饰之后,执行check_in其实是额外执行了login中新增的内容。

我们来解析一下:

当check_in被login装饰后,会自动将check_in 传入到login中,在login的wrapper中,代码是执行print语句和login函数,login将wrapper返回。

仔细看下面:

def login(func):
    def wrapper():
        print("this is wrapper")

        func()

    return wrapper


@login
def check_in():
    print("this is check_in")


print(check_in)

执行结果:

<function login.<locals>.wrapper at 0x000001F97FA1EEE0>

我们可以看到,check_in 实际上是wrapper函数的引用,那么check_in() 和 wrapper() 是一模一样的。而wrapper()不仅执行了传入进来的真实的check_in(),还执行了额外的功能。

 

三、带参数的装饰器

def login(func):
    def wrapper(x):
        print("this is wrapper")

        func(x)

    return wrapper


@login
def check_in(x):
    print("this is check_in")
    print("this is x %d" % x)


check_in(5)

执行结果:

this is wrapper
this is check_in
this is x 5

因为被装饰的check_in需要接收参数,那么就需要让装饰器的内部函数wrapper接收参数,实际上这个参数是给传入的函数引用使用的。

 

四、万能参数装饰器

def login(func):
    def wrapper(*args, **kwargs):
        print("额外的功能")

        func(*args, **kwargs)

    return wrapper


@login
def check_in(x, y=0):
    print("this is check_in")
    print("this is x %d" % x)
    print("this is y %d" % y)


check_in(5, y=1)

执行结果:

额外的功能
this is check_in
this is x 5
this is y 1

 

五、更为完整的装饰器:

def login(s):
    print("this is login")

    print("this is %s" % s)

    def inner(func):

        def wrapper(*args, **kwargs):
            print("额外的功能")

            func(*args, **kwargs)

        return wrapper

    return inner


@login("hello python")
def check_in(x, y=0):
    print("this is check_in")
    print("this is x %d" % x)
    print("this is y %d" % y)


check_in(5, y=1)

执行结果:

this is login
this is hello python
额外的功能
this is check_in
this is x 5
this is y 1

结论:若需要装饰器可以接收参数,那么需要在原有的装饰器外面再套一层。

 

posted @ 2022-02-28 16:24  Target_L  阅读(45)  评论(0)    收藏  举报