zoukankan      html  css  js  c++  java
  • Python_基础_(装饰器,*args,**kwargs,高阶函数,函数闭包,函数嵌套)

    一,装饰器

     装饰器:本质就是函数,功能是为其它的函数动态添加附加的功能

    原则:对修改关闭对扩展开放

    1.不修改被修饰函数的源代码

    2.不修改被修改函数的调用方式

     装饰器实现的知识储备:高阶函数,函数嵌套,函数闭包

    ## 高阶函数

    # 高阶函数的定义:

    1:函数接收的参数是一个参数名

    2:函数的返回值是一个函数名

    3:满足上述的任意一个条件,都可以称为高阶函数

    一,函数接收的参数是一个参数名

    def order():
        print("我是函数order")
    
    def test(func):
        print(func)     # <function order at 0x000002AD351AD378>
        func()          # 我是函数order
    
    test(order)         # 函数的实参是一个函数名,所以接收的参数是一个函数名

    二,函数的返回值是一个参数名

    # 下方程序不合格,函数会重复执行两次(order函数执行两次)
    import time
    def order():
        time.sleep(4)
        print("我是函数order")
    
    def test(func):
        start_time = time.time()
        func()          # 我是函数order
        stop_time = time.time()
        print("函数 %s 的执行是将为%s " %(func,(stop_time - start_time)))
        return func     # 返回值为函数名
    
    test_order = test(order)
    test_order()        # 相当于执行函数 order
    
    # 输出结果
    我是函数order
    函数 <function order at 0x0000029DBEA298C8> 的执行是将为4.035168170928955 
    我是函数order

    ## 函数嵌套

    ## 函数闭包 

    ## 装饰器的架子

    def timmer(func):
        def wrapper():
            print(func)
            func()
        return wrapper

     # 下方的程序解决了重复执行函数问题

    # 下方程序的问题是:对所要计算执行时间的函数都得加上 test = timmer(test)

    import time
    def timmer(func):
        def wrapper():
            start_time = time.time()
            func()    # 运行的为test函数
            stop_time = time.time()
            print("程序运行的时间%s"%(start_time-stop_time))
        return wrapper
    
    
    def test():
        time.sleep(3)
        print("test函数执行完毕")
    
    test = timmer(test)    # 返回函数wrapper地址
    test()    # 执行的时wrapper
    
    # 结果
    test函数执行完毕
    程序运行的时间-3.000077962875366

    ## 语法糖

    # @timmer 相当于 test = timmer(test)

    # 当哪个函数需要加上装饰器,则在函数的上方加上@xxxx 语法糖

    import time
    def timmer(func):
        def wrapper():
            start_time = time.time()
            func()    # 运行的为test函数
            stop_time = time.time()
            print("程序运行的时间%s"%(start_time-stop_time))
        return wrapper
    
    @timmer
    def test():
        time.sleep(3)
        print("test函数执行完毕")
    
    test()    # 执行的是wrapper

    # 当被装饰的函数的参数变化时,装饰器的参数也得变化

    import time
    def timmer(func):
        def wrapper(name,age):
            start_time = time.time()
            func(name,age)    # 运行的为test函数
            stop_time = time.time()
            print("程序运行的时间%s"%(start_time-stop_time))
            print(name,age)
        return wrapper
    
    @timmer
    def test(name,age):
        time.sleep(3)
        print("test函数执行完毕")
    test("henry",18)
    
    @timmer
    def test2(name,age,addr):
        time.sleep(3)
        print("test2函数执行完毕")
    test2("heihei","16","China")
    # 程序报错:当被装饰的函数有三个实参时,装饰器中也得有对应的形参

    # 使用 *args,**kwargs解决,当被装饰的函数的参数变化时,装饰器的参数也得变化的问题

    import time
    def timmer(func):
        def wrapper(*args,**kwargs):
            start_time = time.time()
            func(*args,**kwargs)    # 运行的为test函数
            stop_time = time.time()
            print("程序运行的时间%s"%(start_time-stop_time))
            print(*args,**kwargs)
        return wrapper
    
    @timmer
    def test(name,age):
        time.sleep(3)
        print("test函数执行完毕")
    test("henry",18)
    
    @timmer
    def test2(name,age,addr):
        time.sleep(3)
        print("test2函数执行完毕")
    test2("heihei","16","China")    # 程序不在报错
    
    # 输出
    test函数执行完毕
    程序运行的时间-3.000153064727783
    henry 18
    test2函数执行完毕
    程序运行的时间-3.0007944107055664
    heihei 16 China

    ## 浅浅了解*args与**kwargs

    *args:将多个实参放入一个元组中,可以传多个参数

    **kwargs:按照关键字传值,将多余的值以字典的形式传递

    ## *agrs

    ##  将实参与形参对应的按位置传值,多出来的给grgs
    # 示例1
    def test(a,*args):
        print(a)
        print(args)
    
    test(1,2,3,4,5,6,7)
    # 输出
    1
    (2, 3, 4, 5, 6, 7)
    
    --------------------------------------------------------------
    
    # 示例2(位置参数,默认参数,*args)
    def test(a,b = 1 ,*args):
        print(a)
        print(b)
        print(args)
    
    test(1,2,3,4,5,6,7)    # 1给了a,b=1的值被重置为2,其余的给了args
    # 输出
    1
    2
    (3, 4, 5, 6, 7)
    
    -------------------------------------------------------------
    
    # 示例3(位置参数,*args,默认参数)
    def test(a,*args,b = 1 ):
        print(a)
        print(b)
        print(args)
    test(1,2,3,4,5,6,7)
    # 输出
    1
    1
    (2, 3, 4, 5, 6, 7)
    示例代码

    ## **kwargs(形参中按关键字传值,多余的以自定的形式传递)

    # 示例1 将所有的值给了args
    def test(*args,**kwargs):
        print(args)
        print(kwargs)
    test(1,2,3,4,5)
    # 输出
    (1, 2, 3, 4, 5)
    {}
    
    ---------------------------------------------------------
    
    # 示例2
    def test1(a,**kwargs):
        print(a)
        print(kwargs)
    test1(1,b=2,c=3,d=4)
    # 输出    将1给了a,将其余的以字典的形式给了Kwargs
    1
    {'b': 2, 'c': 3, 'd': 4}
    
    -------------------------------------------------------
    
    # 示例3
    def test3(a,*args,**kwargs):
        print(a)
        print(args)
        print(kwargs)
    test3(1,2,3,4,5,b=6,c=7)
    # 输出
    1
    (2, 3, 4, 5)
    {'b': 6, 'c': 7}
    
    -----------------------------------------------------
    
    # 错误示例
    def test4(z,**kwargs,*args):
        print(z)
        print(kwargs)
        print(args)
    test4(1,y=2,3,4,5)
    # 报错 SyntaxError: invalid syntax
    示例代码

    小小补充:

    num_l = [1,2,3,4,5,6,7,8]
    a,*b,c = num_l
    print(a)
    print(b)
    print(c)
    # 输出
    1
    [2, 3, 4, 5, 6, 7]
    8
    
    注:
    普通调换两个数
    a = 1
    b = 2
    c = a
    a = b
    b = a
    
    Python中的一一对应
    a,b = b,a

    ## 携带参数的装饰器

    import time
    def timmer_test(file_type="aaa"):
        def timmer(func):
            def wrapper(*args,**kwargs):
                if file_type == "aaa":# 执行不同的功能
                    print("携带的参数为aaa")
                elif file_type == "bbb":
                    print("携带的参数为bbb")
                start_time = time.time()
                res = func(*args,**kwargs)    # 运行的为test函数
                stop_time = time.time()
                print("程序运行的时间%s"%(start_time-stop_time))
                return res
            return wrapper
        return timmer
    
    
    @timmer_test(file_type="aaa")    # timmer = timmer_test(file_type="aaa") 最终的结果还是@timmer,已经附加一个file_type
    def test1():
        time.sleep(3)
        print("test函数执行完毕")
    
    @timmer_test(file_type="bbb")   # 携带不同的参数 执行不同的功能
    def test2():
        time.sleep(2)
        print("test函数执行完毕")
    
    test1()
    test2()
    # 输出
    携带的参数为aaa
    test函数执行完毕
    程序运行的时间-3.0003297328948975
    携带的参数为bbb
    test函数执行完毕
    程序运行的时间-2.00068998336792
  • 相关阅读:
    Spring进阶—如何用Java代码实现邮件发送(一)
    如何在Apache中使用PHP处理PHP文件
    最“高大上”的Spring测试:Spring Test
    【编程直播】来约吗?
    【PaPaPa】实现缓存决策
    【PaPaPa】系统架构搭建浅析
    【PaPaPa】集成B/S主流技术的MVC5项目
    【轮子狂魔】手把手教你自造Redis Client
    【轮子狂魔】抛弃IIS,打造个性的Web Server
    【轮子狂魔】抛弃IIS,向天借个HttpListener
  • 原文地址:https://www.cnblogs.com/Doaoao/p/10134718.html
Copyright © 2011-2022 走看看