• 装饰器函数


    函数名的意义:
      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
    意义:业务实现和其他细节隔开,扩展的就是细节.切面就是业务实现
    其他细节就是新的功能
    """
  • 相关阅读:
    sqlserver中临时表、row-number、update更新自己
    easyui 实现Tooltip
    easyui 添加dialog
    转载 50种方法优化SQL Server数据库查询
    用正则将空格给去掉
    java连接redis无法连接,报异常RedisConnectionException
    springcloud的Turbine配置监控多个服务的一些坑!!!!InstanceMonitor$MisconfiguredHostException,No message available","path":"/actuator/hystrix.stream,页面不显示服务或者一直loading
    CentOS7最小化安装之后无法联网以及无法使用ifconfig以及无法使用yum安装软件
    required_new spring事务传播行为无效碰到的坑!
    推荐一下牛逼的谷歌浏览器插件!!!非常好用
  • 原文地址:https://www.cnblogs.com/huaibin/p/12101176.html
Copyright © 2020-2023  润新知