zoukankan      html  css  js  c++  java
  • 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)
    

      

  • 相关阅读:
    龙井和碧螺春的功效与作用
    064 01 Android 零基础入门 01 Java基础语法 08 Java方法 02 无参带返回值方法
    063 01 Android 零基础入门 01 Java基础语法 08 Java方法 01 无参无返回值方法
    062 01 Android 零基础入门 01 Java基础语法 07 Java二维数组 01 二维数组应用
    061 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 08 一维数组总结
    060 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 07 冒泡排序
    059 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 06 增强型for循环
    058 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 05 案例:求数组元素的最大值
    057 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 04 案例:求整型数组的数组元素的元素值累加和
    056 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 03 一维数组的应用
  • 原文地址:https://www.cnblogs.com/tengjiang/p/11604759.html
Copyright © 2011-2022 走看看