python深入之装饰器几种特殊情况

关于装饰器的执行过程

来一段简单的装饰器代码:

def zsq(func):
    def inner():
        print("#" * 10)
        func()
    return inner
@zsq
def print_c():
    print("c")
print_c()

装饰器执行过程:首先系统为两个函数zsq和print_c开辟两个存储空间,在@zsq处执行zsq函数,这里相当于语句print_c=zsq(print_c),于是func指向print_c的空间;然后再在zsq中为函数inner开辟一个空间,其中的内容是print("#" * 10);func(),并将inner函数整体返回给print_c,可知print_c指向inner函数空间;最后调用print_c(),这时执行inner函数的内容。

关于装饰器叠加

(1)装饰器叠加的规则是:从上往下装饰,从下往上执行

(2)语法糖@zsq会对紧跟在其后的函数整体进行装饰,如果其下方紧跟另一个装饰器语法糖,则先执行下面的装饰,然后再对装饰好的函数进行第二次装饰

(3)代码如下:

def zsq(func):
    def inner():
        print("-" * 30)
        func()
    return inner
def zsq1(func):
    def inner():
        print("*" * 30)
        func()
    return inner
@zsq
@zsq1
def print_cont():
    print("666")
print_cont()

关于带参数函数的装饰

(1)被装饰函数带参数时,由装饰器的执行过程可知,需要对装饰器进行修改。但需要注意的是,函数带参个数不能确定,要使得装饰器通用,则要使用不定长参数来传参

(2)带参函数通用装饰器代码如下(注意其中不定长参数的装包和拆包,以及函数传参个数):

def zsq(func):
    def inner(*args, **kwargs):
        print("*" * 30)
        # print(args, kwargs)
        func(*args, **kwargs)
    return inner
@zsq
def print_cont(num, num1, num2):
    print(num, num1, num2)
@zsq
def print_cont1(num):
    print(num)
print_cont(9, 10, num2=18)
print_cont1(10)

关于有返回值函数的装饰

(1)由装饰器执行过程可知,装饰器中的内部函数inner的格式一定要和被装饰函数保持一致,否则装饰出错;这里我们遵循的原则就是:始终保持函数与闭包格式相同

(2)有返回值函数通用装饰器代码如下:

def zsq(func):
    def inner(*args, **kwargs):
        print("*" * 30)
        res = func(*args, **kwargs)
        return res
    return inner
@zsq
def print_cont(num, num1):
    return num + num1
@zsq
def print_cont1(num3):
    print(num3)
print(print_cont(9, 10))
print(print_cont1(20))

关于带参数的装饰器

(1)前面提到的装饰器叠加,如果几个装饰器的格式和内容几乎相同,只是其中的某个参数发生改变,这时我们就想到利用函数传参的方式对代码进一步简化。但是需要注意的是,装饰器格式是固定的,只能传入要装饰的函数,不能额外传入其他参数,所以这里利用闭包思想,使用闭包嵌套方法,利用一个新的函数来返回装饰器,在新函数中传入参数即可

(2)带参装饰器代码如下:

def return_zsq(char):
    def zsq(func):
        def inner():
            print(char * 10)
            func()
        return inner
    return zsq
# def zsq1(func):
#     def inner():
#         print("*" * 10)
#         func()
#     return inner
@return_zsq("&")
# @zsq1
def print_cont():
    print("我是谁?")
print_cont()

猜你喜欢

转载自blog.csdn.net/zx870121209/article/details/81162474