Day 11 闭包函数.装饰器

1.闭包函数:在函数内部定义一个函数,并且内部函数引用了外部函数的变量

def outer(x,y):   
    def my_max():
        if x > y:  # 引用了outer 的参数,相当与引用了 outer的变量  为闭包函数
            return x
        return y
    return my_max


res = outer(80,90)
print(res())

2.装饰器: 开放封闭原则(对扩展开放对修改封闭) 

  装饰器必须要遵守两个原则 1:不改变被装饰对象的源代码  2 不改变被装饰对象的调用方法

  插入:time模块:

def outer(x,y):   
    def my_max():
        if x > y:  # 引用了outer 的参数,相当与引用了 outer的变量  为闭包函数
            return x
        return y
    return my_max


res = outer(80,90)
print(res())
  1. 装饰无参数的函数
    # 需求:装饰器统计函数运行的时间
    import time
    def f():
        time.sleep(1)
        print("我是f")
    
    def outter(func):  # 这里的func形参被传入实参f函数的内存地址
        def inner():
            start = time.time()
            func()  # 这里调用的是最初的f函数
            end = time.time()
            return end - start
        return inner  # 将inner函数的内存地址返回
    
    
    f = outter(f)   # 先执行括号里的,将原f以参数的方式传给outter返回 inner的内存地址,之后调用新定义的f,就等于调用了inner
    print(f())  # f() 就相当于调用了inner
  2. 装饰有参数的函数
    import time
    def f(name):
        time.sleep(1)
        print(f"我是{name}")
    
    def outter(func):   # 这里的func形参被传入实参f函数的内存地址
        def inner(name):  # 参数name是f的参数name
            start = time.time()
            func(name)  # 这里调用的是最初的f函数
            end = time.time()
            return end - start
        return inner
    
    
    f = outter(f)   # 先执行括号里的,将原f以参数的方式传给outter返回 inner的内存地址,之后调用新定义的f,就等于调用了inner
    print(f('yanglingayo'))  # f() 就相当于调用了inner

  3. 装饰器语法糖:语法糖在装饰的时候要紧挨着被装饰函数,当多个装饰器装饰一个函数顺序是重上至下,执行时候时由下至上
    import time
    def outter(func):
        def inner(name):
            start = time.time()
            func(name)
            end = time.time()
            return end - start
        return inner
    
    @outter  # 用@加上装饰器函数名表示,放置于被装饰函数的上方 此时等价与 f = outter(f)
    def f(name):
        time.sleep(1)
        print(f"我是{name}")
    
    
    print(f('yanglingayo'))
  4. 装饰器的模板  
    def outter(func):
        def inner(*args,**kwargs):
            print('执行被装饰函数之前 你可以做的操作')
            res = func(*args,**kwargs)
            print('执行被装饰函数之后 你可以做的操作')
            return res
        return inner
  5. 多个装饰器装饰一个函数
  6. 装饰器最终模板
    from functools import wraps
    def outter(func):
        @wraps(func)  # 装饰器修复技术
        def inner(*args,**kwargs):
            print('执行被装饰函数之前 你可以执行的操作')
            res = func(*args,**kwargs)
            print('执行被装饰函数之后 你可以执行的操作')
            return res
        return inner
  7. 多层装饰器 
    def outter1(func1):
        print('加载了outter1')
        def wrapper1(*args,**kwargs):
            print('执行了wrapper1')
            res1=func1(*args,**kwargs)
            return res1
        return wrapper1
    def outter2(func2):
        print('加载了outter2')
        def wrapper2(*args,**kwargs):
            print('执行了wrapper2')
            res2=func2(*args,**kwargs)
            return res2
        return wrapper2
    def outter3(func3):
        print('加载了outter3')
        def wrapper3(*args,**kwargs):
            print('执行了wrapper3')
            res3=func3(*args,**kwargs)
            return res3
        return wrapper3
    @outter1  # index = outter1(wapper2)
    @outter2  # wrapper2 = outter2(wrapper3)
    @outter3  # wrapper3 = outter3(最原始的index函数内存地址)
    def index():
        print('from index')

    这个我的理解是把被装饰的函数当作一个中心,他没被装饰一次就在他外面加了一层壳,当我调用执行这个被装饰的函数时,他就像是要拨开这层壳.从外层往里面一层层拨在这个过程会先由外向内的执行每层被装饰函数之前执行的操作,当最终被装饰函数执行完之后 在由内向外的执行每个装饰器在执行完每层被装饰函数的操作,就像用一根针从要穿透一个有3层蛋壳的鸡蛋

  

原文地址:https://www.cnblogs.com/yanglingyao/p/11171746.html