装饰器函数

函数名的意义:
  1.>就是存有函数代码空间的引用的对象
  2.>对象可以将引用传递给其他对象
  3.>该对象可以接收来自其他对象的引用

函数名<也是一个对象>就是指向函数代码的引用.
对象既可以把引用传给别人,也能接收别人的引用.

应用:调用底层的,使用底层的  因为Python有很多使用其他语言写好的库,性能非常好,直接调用就可以.

开闭原则:

  1.>对已经实现了的代码是关闭的, 不允许的.
  2.>对 功能扩展是开放的,允许的.

总结起来就是:在不修改原有代码的情况下添加了新的功能

def check(func):  # check就是装饰器函数.func是一个形参,位置形参
    def inner():
        print('正在检查 ing 123')
        print('即将开始运行func')
        func()  # 保留了f1的引用
        print('已经运行完成了')

    return inner


def check1(*args, **kwargs):  # check就是装饰器函数.func是一个形参,位置形参
    """虽然函数形式上可以接收多个参数,但是在装饰器中只能接收一个参数<被装饰的函数的函数名>"""
    func = args[0]

    def inner():
        print('正在检查')
        func()  # 保留了f1的引用

    return inner


# @装饰器语法  就是对 函数名= 装饰器函数<函数名> 的封装
@check  # 记住:是在定义函数的上边一行,不是在调用函数的时候加
def f1():
    print('running in f1')


"""等价于下面:
@check
def f1():
    pass
f1 = check(f1)   灵魂代码   完成对f1的装饰


问题:
    1.>本行中的f1还是原来的f1对象吗?  
    不是,是check函数的返回值内部函数的引用
        
    2.>check函数中的func参数的意义
    func是一个参数,来接收被装饰的函数的函数名.
    
特点:
"""

# 装饰器函数是基于闭包实现的,<嵌套,返回内部引用,环境变量>
# 装饰器的目的:不修改原有代码的情况下,进行新功能的扩展
# 装饰器函数的特点:
# 把f1装饰成  f2
# f2 = check(f1)  # 把f1函数给check传进去,让他去处理f1
# f2()
# 直接换成f1也行,就是把f1原来引用换到了f2
# f1 = check(f1)  # 把f1函数给check传进去,让他去处理f1
# f1()

f1()

"""
应用场景:
1.程序日志
2.函数运行时间
3.执行函数前的预备处理<安全检查>
4.执行函数后的清理处理
5.权限校验
6.缓存  见前面的例子
7.请求重试(这个是最常见,最常使用的)
"""

函数的运行时间统计:

import time

def get_time(func):  # 这里只能接收一个参数,即使写成了*args **kwargs的形式
    """对函数运行时间进行统计"""
    print('in get_time')  # 灵魂代码  一旦装饰就执行

    def inner(*args, **kwargs):  # 传参数,打包  内部函数可以接收任意参数
        t1 = time.time()
        # 拆包参数  如果函数有返回值,暂时先保存,执行结束在返回
        # 这里的* 和** 是拆包的作用,将刚刚打包的参数进行解包
        res = func(*args, **kwargs) # 暂时先保存执行结果
        t2 = time.time()
        print('运行了%s s' % (t2 - t1))
        # 如果 这里是 func(*args, **kwargs) 那么就会把func又执行了一遍,多余.
        return res  # 返回执行结果
    return inner


# return get_time

# 先写函数

@get_time  # 只要这样写,就把 装饰器执行了
def func1(num,age = 18):
    for i in range(3):
        time.sleep(1)
        print('in func', num,age)


@get_time  # 灵魂代码
def func2(num,height = 180,**kwargs):
    time.sleep(2)
    print('in f2', num,height)
    print(kwargs)
    return 250

#
# func1(222)
#
# func2(999,minzgi = 333)
# 装饰器分为装饰器函数<基于闭包实现>,类装饰器<基于类实现>
# 装饰器函数的特点:有 且 只有一个函数 ,就是被装饰的函数的引用
# 不写return  和return None是一样的


"""
装饰器带参数  @装饰器(参数)
类装饰器
多个装饰器 装饰器



函数:函数代码空间的引用,可以传递,可以接收其他的引用

面向切面编程:AOP
意义:业务实现和其他细节隔开,扩展的就是细节.切面就是业务实现
其他细节就是新的功能
"""
原文地址:https://www.cnblogs.com/huaibin/p/12101176.html