zoukankan      html  css  js  c++  java
  • (4)python装饰器

    【1】前置知识储备

    详细参考上一篇博文:https://www.cnblogs.com/gered/p/13954411.html#autoid-1-3-0

    【1.1】函数即变量

    在数字、字符串变量中,我们之前的数据类型文章中就说了,它是不可以修改的,因为它是放在内存堆中。如果修改就是新赋值,就是在内存堆中重新开辟了一个字符串/数字,然后把变量指向它;

    字符串举例:

      如果有 x=1,y=x,那么这个时候, x 和 y都是引用指向 1 的内存地址,x 如果修改不影响 y。

           那么这个内存中的1什么时候被回收呢?  当该内存存储地址没有被任何变量、函数等引用指向的话,就会随着python默认的刷新检测机制检测发现没有任何引用,就会把它回收掉:

    函数同理:

      那么同理,函数名也是一个引用指针,指向内存中存储函数体的这一块地址。这个我们从匿名函数形式 就可以比较直观的看出来;

    【1.2】高阶函数

    (1)把函数名做实参传给另外一个函数的形参(这也就表达了,高阶函数可以在不修改被装饰函数代码的情况下,为其添加功能)

    (2)返回值中包含函数名(不修改函数的调用方式的情况下,为其添加功能)

    【1.3】嵌套函数

    嵌套函数,就是在函数的内部用def 定义另外的函数

    【2】装饰器:基本形式(就是高阶函数+嵌套函数)

    装饰器:本质上是函数,是用来装饰其他函数的(就是为其他函数添加附加功能)
    原则(1):不能修改被装饰的函数的源代码
    原则(2):不能修改被装饰的函数的调用方式
    即:装饰器对函数来说是完全透明的,就是说函数感知不到装饰器的存在,也就函数的源代码和调用方式都没有被改变

    (1)好理解的形式(无参数)

    import time
    def test1():
        time.sleep(3)
        print('in the test1')
    
    def test2():
        time.sleep(3)
        print('in the test2')
    
    def timer(func):  # timer(test1) func=test1
        def deco():
            start_time=time.time()
            func()  # run test1()
            stop_time=time.time()
            print('run the fun used {} second'.format(stop_time-start_time))
        return deco
    
    test1 = timer(test1)
    test1()

    in the test1
    run the fun used 3.0009162425994873 second

    ~~~实现了不修改函数源代码,也不修改函数调用方式,添加了新功能 输出函数执行使用时间

    (2)语法糖:即用 @装饰器名  放到函数定义的上一行(带参数)

    不带参数的函数也可以用 这种装饰器

    import time
    def timer(func):
        def warpper(*args,**kwargs):
            start_time=time.time()
            func(*args,**kwargs)
            stop_time=time.time()
            print('the func run time is {} '.format(stop_time-start_time))
        return warpper
    @timer # 这里实现了 test1 = timer(test1) 的功能
    def test1(a,b,c): time.sleep(3) print('this is test1!')
    print(a,b,c)

    test1(1,2,3)

    this is test1!
    the func run time is 3.000502824783325

    (3)返回值的参数

    import time
    user, passwd = 'gg', '123456'
    def auth(func):
        def wrapper(*args, **kwargs):
            username = input("Username:").strip()
            password = input("Password:").strip()
            if user == username and passwd == password:
                print("33[32;1m User has passed authentication33[0m")
                res = func(*args, **kwargs)
    print('函数运行完毕')
    return res
    else: exit("33[31;1m Invalid Username or Password 33[0m") return wrapper def index(): print("welcome to index page") @auth def home(): print("welcome to home page")
    return '我是home函数的返回值' @auth
    def bbs(): print("welcome to bbs page") index() print(home())

    welcome to index page
    Username:gg
    Password:123456
    User has passed authentication
    welcome to home page
    函数运行完毕
    我是home函数的返回值

    (4)高潮迭起的装饰器:装饰器本身参数

    # 根据装饰器参数,区分函数类别
    
    user, passwd = 'gg', '123456'
    def auth(auth_type):
        print("auth func type:",auth_type)
        def out_wrapper(func):
            def wrapper(*args, **kwargs):
                if auth_type == 'bbs':
                    username = input("Username:").strip()
                    password = input("Password:").strip()
                    if user == username and passwd == password:
                        print("33[32;1m User has passed authentication33[0m")
                        res = func(*args, **kwargs)
                        print('函数运行完毕')
                        return res
                    else:
                        exit("33[31;1m Invalid Username or Password 33[0m")
                elif auth_type == 'home':
                    print('自己直接访问就可以了啊,不需要做登录验证')
                else:
                    print('又不是自己家,又不是bbs,滚蛋!')
            return wrapper
        return out_wrapper
    
    def index():
        print("welcome to index page")
    
    @auth('home')
    def home1():
        print("welcome to home1 page")
        return '我是home1函数的返回值'
    @auth('home')
    def home2():
        print("welcome to home1 page")
        return '我是home1函数的返回值'
    
    @auth('bbs')
    def bbs1():
        print("welcome to bbs page")
    @auth('bbs')
    def bbs2():
        print("welcome to bbs page")
    
    index()
    home1()
    bbs1()

    auth func type: home
    auth func type: home
    auth func type: bbs
    auth func type: bbs
    welcome to index page
    自己直接访问就可以了啊,不需要做登录验证
    Username:gg
    Password:123456
    User has passed authentication
    welcome to bbs page
    函数运行完毕

  • 相关阅读:
    VS2019调试 asp.net core 2.2 出现《ANCM In-Process Handler Load Failure 发布后启动错误处理》处理
    网页上显示数学公式的三种方案
    FileStream实现多线程断点续传(已封装)
    绝对定位不脱离文档流的方法
    百度地图InfoWindow弹窗圆角
    并发:线程池异步执行与创建单独的线程执行
    互斥锁和自旋锁的区别
    事务的特性和隔离级别
    线程不安全与线程安全示例
    多线程过去与现在
  • 原文地址:https://www.cnblogs.com/gered/p/13964196.html
Copyright © 2011-2022 走看看