• Python之装饰器


    装饰器学习

    一、装饰器

    1、什么是装饰器

    装饰器本质就是函数,是为其他函数添加附加功能;

    2、装饰器原则

    a、不修改被装饰函数的源代码;

    b、不修改被装饰函数的调用方式;

    c、不能违反开放封闭原则:程序一旦上线,不能更改内部源代码,一旦更改程序内部源代码,就可能产生问题;

    3、装饰器的知识储备

    装饰器=高阶函数+函数嵌套+闭包

    (1)、高阶函数定义

    a、函数接收的参数是一个函数

    b、函数的返回值是一个函数;

    c、满足上面条件中的任意条件都可称之为高阶函数;

    #!/usr/bin/env python
    # _*_ coding:utf-8 _*_
    #使用高阶函数为函数foo添加一个统计运行时间的功能;
    ##功能已经实现,没有违反修改程序源代码,没有违反函数调用方式;
    #但是从运行结果来看,程序运行了两遍,该方法不行;
    import time
    def foo():
        time.sleep(3)
        print("来自foo函数")
    def timer(func):
        start_time = time.time()
        func()
        end_time = time.time()
        print("函数%s的的运行时间为:%s" %(func,end_time-start_time))
        return func
    foo = timer(foo)
    foo()     
    """
    来自foo函数
    函数<function foo at 0x0000022DDB7729D8>的的运行时间为:3.008920431137085
    来自foo函数
    """
    

     (2)、函数嵌套

    函数内部调用函数不表函数嵌套,函数内部重新定义了一个函数叫函数嵌套;

    #!/usr/bin/env python
    # _*_ coding:utf-8 _*_
    ###这不是函数嵌套
    import time
    def foo():
        time.sleep(3)
    def bar():
        print("来自bar函数")
        foo()
        print("当前时间为:%s" %time.time())
    bar()
    

     上面的函数不是函数嵌套

    #!/usr/bin/env python
    # _*_ coding:utf-8 _*_
    import time
    def bar():
        print("来自bar函数")
        def foo():
            time.sleep(3)
        print("当前时间为:%s" %time.time())
    bar()
    

     这才是函数嵌套

    (3)、函数闭包

    #!/usr/bin/env python
    # _*_ coding:utf-8 _*_
    def father(name):
        print("来自father函数")
        def son():
            print("我的爸爸是%s" %name)
            def grandson():
                name = "就是我自己"
                print("我的爷爷是%s" %name)
            grandson()
        son()
    father("尼古拉斯赵四")
    

     

     函数闭包其实函数作用域

    #!/usr/bin/env python
    # _*_ coding:utf-8 _*_
    import time
    def test():
        time.sleep(3)
        print("test函数运行完毕")
    def timer(func):
        def wrapper():
            start_time = time.time()
            func()
            end_time = time.time()
            print("函数func的运行时间为:%s" %(end_time-start_time))
        return wrapper
    test = timer(test)
    test()
    """输出结果:
    test函数运行完毕
    函数func的运行时间为:3.02397084236145
    
    """
    #备注:a、没有修改程序内部代码;b、没有修改程序的调用方式;
    #完成了为程序添加附加功能
    

      4、语法糖

    #!/usr/bin/env python
    # _*_ coding:utf-8 _*_
    import time
    ##装饰器
    def timer(func):
        def wrapper():
            start_time = time.time()
            func()
            end_time = time.time()
            print("函数func的运行时间为:%s" %(end_time-start_time))
        return wrapper
    #原函数
    @timer #函数优化:语法糖@timer= test = timer(test),在原函数前面加上@timer
    def test():
        time.sleep(3)
        print("test函数运行完毕")
    test()
    

     函数再次优化,获取test函数的返回值

    #!/usr/bin/env python
    # _*_ coding:utf-8 _*_
    import time
    ##装饰器
    def timer(func):
        def wrapper():
            start_time = time.time()
            ###获取test函数的返回值
            res = func()
            end_time = time.time()
            print("函数func的运行时间为:%s" %(end_time-start_time))
            return res
        return wrapper
    #原函数
    @timer #函数优化:语法糖@timer= test = timer(test),在原函数前面加上@timer
    def test():
        time.sleep(3)
        print("test函数运行完毕")
        return "这是来自test函数的运行结果"
    res = test() ##此时test()就是在运行wrapper函数
    print(res)
    

     (1)、装饰器修改多个带参的函数

    #!/usr/bin/env python
    # _*_ coding:utf-8 _*_
    import time
    ##装饰器
    def timer(func):
        def wrapper(*args,**kwargs):
            start_time = time.time()
            ###获取test函数的返回值
            res = func(*args,**kwargs)
            end_time = time.time()
            print("函数%s的运行时间为:%s" %(func,end_time-start_time))
            return res
        return wrapper
    ###当装饰器修饰带参的函数且为多个函数时,由于每个被修饰的函数的
    ###形参个数不同,为了使装饰器接收任意长度的参数,故将装饰器函数的
    ###参数写为可以接收任意长度,任意类型的形参
    #原函数
    @timer #函数优化:语法糖@timer= test = timer(test),在原函数前面加上@timer
    ####优化原函数为带参的参数
    def test(name,age,gender):
        time.sleep(3)
        print("test函数运行完毕")
        return "这是来自test函数的运行结果"
    @timer
    def test1(name,age,gender,addr):
        time.sleep(3)
        print("test1函数运行完毕")
        return "这是来自test1函数的运行结果"
    res = test("尼古拉斯赵四",19,"male") ##此时test()就是在运行wrapper函数
    print(res)
    res1 = test1("尼古拉斯赵四",19,"male","重庆市")
    print(res1)
    

     (2)、解压序列:这种方法非常有用,可以快速地取到最大值和最小值

    #!/usr/bin/env python
    # _*_ coding:utf-8 _*_
    #解压序列
    l = (1,2,3)
    a,b,c =l
    print(a,b,c) #1 2 3
    #使用解压序列进行取值:去掉最高分和去掉最低分
    l = [10,2,4,5,6,7,8,9,9,4]
    #升序排列
    l.sort()
    #这种解压序列可以很快就取到第一位和最后一位;
    #*_表示中间的所有值
    a,*_,b = l
    print("最低分为:%s,最高分为:%s" %(a,b)) #print("最低分为:%s,最高分为:%s" %(a,b))
    print(*_)  #4 4 5 6 7 8 9 9
    

     (3)、补充:两变量值互相交换

    #!/usr/bin/env python
    # _*_ coding:utf-8 _*_
    a = 1
    b = 2
    x = a
    a = b
    b = x
    print(a,b)
    f1 = 1
    f2 = 2
    f1,f2 = f2,f1
    print(f1,f2)
    

     (4)、为函数加上验证功能:

    #!/usr/bin/env python
    # _*_ coding:utf-8 _*_
    import time
    def timer(func):
        def identer(*args,**kwargs):
    
            while True:
                name = input("请输入用户名:")
                password = input("请输入密码:")
                if name == "zhangsan@163.com" and password == "zhangsan":
                   print("欢迎登陆:%s,登陆时间为:%s" %(name,time.time()))
                   start_time = time.time()
                   res = func(*args, **kwargs)
                   end_time = time.time()
                   print("函数%s运行时间为:%s" % (func, end_time - start_time))
                   return res
                   break
                else:
                    print("用户名或者密码输入错误,请重新输入!!!!!")
    
    
    
    
        return identer
    @timer
    #原函数加上验证功能
    def index():
        pass
    @timer
    def home():
        pass
    @timer
    def shopping_cat():
        pass
    @timer
    def order():
        pass
    res = home()
    print(res)
    

      

  • 相关阅读:
    Gitlab的安装
    转 Java操作PDF之iText详细入门
    ElasticSearch聚合(转)
    谷歌搜索技巧(转)https://www.runningcheese.com/google
    自学elastic search
    WinForm richtextbox 关键字变红色
    https采集12306(复制)
    LTS
    学习Android MediaPlayer
    UML基础知识
  • 原文地址:https://www.cnblogs.com/tengjiang/p/11604759.html
Copyright © 2020-2023  润新知