美文网首页
装饰器 decorator

装饰器 decorator

作者: 午字横 | 来源:发表于2023-04-24 13:41 被阅读0次
闭包
# 闭包
def Print_A(a):
    def Print_B(b):
        print(a,b)
    return Print_B

temp=Print_A("a")
temp("b")

闭包用到的核心其实就是:在一个函数中返回另外一个函数的引用,只不过这个被返回的函数中用到了其他函数中的变量而已。说到底就是 只要用一个变量指向某个函数代码块,就可以调用它

# 装饰器
def check_login(func):
    print("1:---------------")
    def check():
        print('check')
        func()
        print("done:---------------")

    print("2:---------------")
    return check

@check_login
def login():
    print('login')

login()


输出:
1:---------------
2:---------------
check
login
done:---------------

Process finished with exit code 0

当Python解释器对上述代码运行时,会从上到下解释代码,步骤如下:
遇到def check_login(func): 将check_login函数加载到内存
执行@check_login
没错, 从表面上看解释器仅仅会解释这两句代码,因为函数在 没有被调用之前其内部代码不会被执行。
从表面上看解释器着实会执行这两句,但是@check_login这一句代码里却有大文章, @xxx 是Python的一种语法糖(简单理解为令你很惊奇的功能)
其实就像相当于下边这两句:”
login=check_login(login)
login()

对带有参数的函数进行装饰
#对带有参数的函数进行装饰

def decroator_run(func):
    def xxx(a,b):
        print("xxx执行了")
        func(a,b)
        pass

    return xxx

@decroator_run
def run(a,b):
    print(a,b)


run("a","b")
通用装饰器
#通用装饰器
def decroator_run(func):
    def xxx(*name):
        print("xxx执行了")
        func(name)
        pass

    return  xxx

@decroator_run
def run(*name):
    print(name)

run("a")
run("a","b")
对带有return的函数进行装饰
# 对带有return的函数进行装饰

def decroator_run(func):
    def xxx():
        temp= func()
        pass
        return  temp

    return xxx

@decroator_run
def run():
    return "run done"

print(run())
s 多个装饰器对同一个函数进行装饰
# 多个装饰器对同一个函数进行装饰
def decroator_run_01(func):
    def xxx():
        return func()+"AAA"
        pass
    return xxx

def decroator_run_02(func):
    def xxx():
        return func()+"BBB"
        pass
    return xxx

@decroator_run_01
@decroator_run_02
def run():
    return "run"

print(run())


输出:
runBBBAAA

Process finished with exit code 0
#装饰器带参数
# 多个装饰器对同一个函数进行装饰
def decroator_run_01(name):
    def x(func):
        def xxx():
            print(name)
            return func() + "AAA"
            pass

        return xxx
    return x


@decroator_run_01(100)
def run():
    return "run"

print(run())
用类当做装饰器
#用类当做装饰器
class Test(object):
    def __init__(self, func):
        print("---初始化---")
        print("func name is %s" % func.__name__)
        self.__func = func
    def __call__(self):
        print("---装饰器中的功能---")
        self.__func()


@Test
def test():
    print("----test---")


test()  # 如果把这句话注释,重新运行程序,依然会看到"--初始化--"

  1. 当用Test来装作装饰器对test函数进行装饰的时候,首先会创建Test的实例对象
    并且会把test这个函数名当做参数传递到init方法中
    即在init方法中的属性__func指向了test指向的函数
  2. test指向了用Test创建出来的实例对象
  3. 当在使用test()进行调用时,就相当于直接调用实例对象,因此会调用这个对象的call方法
  4. 为了能够在call方法中调用原来test指向的函数体,所以在init方法中就需要一个实例属性来保存这个函数体的引用
    所以才有了self.__func = func这句代码,从而在调用call方法中能够调用到test之前的函数体

6. 总结

  1. 装饰器:能够快速将函数的指向修改,能够在不修改代码的前提下,给函数添加功能的方式
  2. 装饰器功能:给函数添加功能
  3. 特点:不修改原函数代码,还能添加功能;只能在原函数运行之前或者之后添加,不能在原函数运行一半时添加
  4. 实现过程:1. 将原函数的引用当做实参传递到闭包中 2. 修改原函数的指向为闭包中的内部函数
  5. 装饰器实际上用到了闭包,只不过在给外层函数传递参数时,传递的是需要被装饰的函数引用而已
  6. 装饰器还用到了引用,即在Python中,a=xx那么无论xx是列表、字典还是对象,一定是a指向它,而不是存储它

2023-04-25

相关文章

网友评论

      本文标题:装饰器 decorator

      本文链接:https://www.haomeiwen.com/subject/hqrujdtx.html