• 函数和常用模块【day05】:装饰器高潮(三)


    本节内容

    1、概述

    2、装饰器定义

    3、装饰器定义

    4、带参数的生成器

    一、概述

    我们之前介绍了大幅片的内容,感觉跟装饰器半毛钱关系都没有,其实不然,我们分别详细阐述了高阶函数和内置函数,下面我们就来讲讲什么是真正的装饰器。

    二、装饰器定义

    首先装饰器实现的条件:高阶函数+嵌套函数 =》装饰器

    1、定义

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    import time
     
    #定义内置函数
    def timmer(func):  #timmer(test1) func=test1
        def deco():
            start_time = time.time()
            func()   #run test1()
            stop_time = time.time()
            print("the func run time is %s"%(stop_time-start_time))
     
        return deco
     
    #装饰test1函数
    @timmer  # 相当于test1 = timmer(test1)
    def test1():
        time.sleep(3)
        print("in the test1")
     
    #直接执行test1函数   
    test1()
     
    #输出
    in the test1
    the func run time is 3.0002999305725098

     执行步骤:

    1. 执行timmer函数,timmer(test1) 返回值赋值给test1变量,即test1=timmer(test1)
    2. 此时的test1的值是执行timmer函数返回值deco,即test1=deco
    3. 所以执行test1,其实就是执行的是deco函数,test1()其实就是执行deco函数。

    2、执行函数带参数

    我们先来试试,如果被装饰的函数需要传入参数怎么办?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    import time
     
    def timmer(func):  #timmer(test1) func=test1
        def deco():
            start_time = time.time()
            func()   #run test1()
            stop_time = time.time()
            print("the func run time is %s"%(stop_time-start_time))
     
        return deco
     
    @timmer
    def test2(name,age):
        print("name:%s,age:%s"%(name,age))
     
    test2()
     
    #输出
    Traceback (most recent call last):
      File "D:/PycharmProjects/pyhomework/day4/装饰器/装饰器高潮.py", line 23in <module>
        test2()
      File "D:/PycharmProjects/pyhomework/day4/装饰器/装饰器高潮.py", line 8in deco
        func()   #run test1()
    TypeError: test2() missing 2 required positional arguments: 'name' and 'age' #缺少传入name和age参数

     很显然是错误的,错误的。因为这边执行的test2函数其实就是执行的deco函数,deco函数体内的func()其实就是执行test2函数,但是,test2需要传入name和age两个参数,所以报错。那怎么解决呢?我们只能传入参数了,但是你又不能确定传入几个参数,所以我们只能用非固定参数传参。代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    import time
     
    def timmer(func):  #timmer(test1) func=test1
        def deco(*args,**kwargs):  #传入非固定参数
            start_time = time.time()
            func(*args,**kwargs)   #传入非固定参数
            stop_time = time.time()
            print("the func run time is %s"%(stop_time-start_time))
     
        return deco
     
    #不带参数
    @timmer  # 相当于test1 = timmer(test1)
    def test1():
        time.sleep(3)
        print("in the test1")
     
    #带参数
    @timmer
    def test2(name,age):
        print("name:%s,age:%s"%(name,age))
    #调用
    test1()
    test2("zhangqigao",22)
     
    #输出
    #test1
    in the test1
    the func run time is 3.0010883808135986
    #test2
    name:zhangqigao,age:22
    the func run time is 0.0  #test2

    三、执行函数有返回值

    上面的例子,被调用的函数都没有返回值,那如果,我们被调函数有返回值,该如何做呢?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    def timmer(func):  #timmer(test1) func=test1
        def deco(*args,**kwargs):
            res = func(*args,**kwargs) #这边传入函数结果赋给res
            return res   # 返回res
        return deco
     
    @timmer
    def test1():  # test1 =  timmer(test1)
        print("in the test1")
        return "from the test1" #执行函数test1有返回值
     
    res = test1()
    print(res)
     
    #输出
    in the test1
    from the test1

     通过上面的例子,可以看出,其实就是在内置函数中把传入参数的执行结果赋给res,然后再返回res变量。

    四、带参数的装饰器

    之前我们的装饰器都是没有带参数的,其实我们已经能解决90%的问题了,但是如果说有一种情况:就是在你访问不通页面时,你用的验证的方式来源不同,这时你该怎么办?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    #本地验证
    user,passwd = "zhangqigao","abc123"
     
    def auth(auth_type):  #传递装饰器的参数
        print("auth func:",auth_type)
        def outer_wrapper(func):   # 将被装饰的函数作为参数传递进来
            def wrapper(*args,**kwargs):  #将被装饰函数的参数传递进来
                print("wrapper func args:",*args,**kwargs)
                username = input("Username:").strip()
                password = input("Password:").strip()
                if auth_type == "local":
                    if user == username and passwd == password:
                        print("33[32mUser has passed authentication33[0m")
                        res = func(*args,**kwargs)
                        print("--after authentication")
                        return res
                    else:
                        exit("Invalid username or password")
                elif auth_type == "ldap":
                    pass
            return wrapper
        return outer_wrapper
     
    def index():
        print("welcome to index page")
     
    @auth(auth_type="local")  #带参数装饰器
    def home():
        print("welcome to home page")
        return "from home"
     
    @auth(auth_type="ldap")   #带参数装饰器
    def bbs():
        print("welcome  to bbs page")
     
    index()
    home()
    bbs()

     重上面的例子可以看出,执行步骤:

    1. outer_wrapper = auth(auth_type="local")
    2. home = outer_wrapper(home)
    3. home()

    所以这个函数的作用分别是:

    1. auth(auth_type) 传递装饰器的参数
    2. outer_wrapper(func) 把函数当做实参传递进来
    3. wrapper(*args,**kwargs) 真正执行装饰的函数
  • 相关阅读:
    Using Project Custom Properties to replace all end point of test cases
    Jacoco Code coverage with Robotframework Maven pom.xml example
    Jacoco Code coverage with Robotframework
    Test coverage in a multi module Maven project
    如何让linux的history命令显示时间记录
    项目角色职责分配表
    Linux检查哪些thread在占用CPU
    soapui_mockservicerunner_script.sh
    Some api interface link of Soapui
    GlusterFS分布式存储系统
  • 原文地址:https://www.cnblogs.com/luoahong/p/9889951.html
Copyright © 2020-2023  润新知