• python基础09--函数闭包与装饰器


    装饰器:

    本质:就是一个函数

    功能:为其他函数添加附加功能

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

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

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

    高阶函数:结合两种高阶函数的方式,不能满足装饰器的功能,多执行了一次操作

    import time
    def foo():
        print("来自foo")
    def test(func):
        print("来自test")
        start_time=time.time()
        func()
        end_time=time.time()
        print("运行时间%s" %(start_time-end_time))
        return func
    foo=test(foo)  
    foo()
    View Code

    装饰器的基本实现

    import time
    def foo(func):   #func=test
        def too():
            start_time=time.time()
            func()
            end_time=time.time()
            print("运行时间%s" %(start_time-end_time))
        return too
    
    @foo
    def test():
        time.sleep(3)
        print("函数运行完毕")
    # test=foo(test)       #修改了一部分源代码,可在函数前加上@foo(完成了test=foo(test)的操作),表示调用装饰器内容
    # test()
    test()
    View Code

    ps:1.返回值的问题,保存test函数中的返回值,装饰器中需要有变量接收返回的值

    import time
    def foo(func):   #func=test
        def too():
            start_time=time.time()
            res=func()    #***接收test的返回值
            end_time=time.time()
            print("运行时间%s" %(start_time-end_time))
            return res   #***最终返回res的值
            
        return too
    
    @foo
    def test():
        time.sleep(3)
        print("函数运行完毕")
        return "test的返回值"
    # test=foo(test)    #返回的是too的地址
    #  test()          #执行too
    # #修改了一部分源代码,可在函数前加上@foo(完成了test=foo(test)的操作),表示调用装饰器内容
    
    res=test()
    print(res)
    View Code

           2. 加入参数,利用可变长参数接收各种类型的数据

    import time
    def foo(func):   #func=test
        def too(*args,**kwargs):  #保证参数原封不动原给下一个func
            start_time=time.time()
            res=func(*args,**kwargs)
            end_time=time.time()
            print("运行时间%s" %(start_time-end_time))
            return res
    
        return too
    
    @foo
    def test(name,age,gender):    #(name,age,gender)=("alex",12,"male) 通过解压序列,获得一一对应的关系传入
        time.sleep(3)              
        print("函数运行完毕","我是%s,年龄为%s,性别是%s" %(name,age,gender))
        return "test的返回值"
    
    res=test("alex",12,"male")
    print(res)
    View Code

    ps:解压序列:

    取开头和结尾的值:

    l=(1,23,4354,76,8,)
    a,*_,c=l         #*_表示中间的全部数
    print(a,c)
    View Code

    位置调换:

    a1=1
    a2=2
    a1,a2=a2,a1
    print(a1,a2)
    View Code

    加上验证功能例子:

    user_list=[{"username":"alex","passwd":"123"},{"username":"sb","passwd":"abc"},{"username":"baby","passwd":"456"}]
    current_dic={"username":None,"login":False}
    def fangfa(func):
        def foo(*args,**kwargs):
            if current_dic["username"] and current_dic["login"]:
                res=func(*args,**kwargs)
                return res
    
            username=input("用户名:").strip()
            passwd=input("密码:").strip()
            for user_dic in user_list:
                if username== user_dic["username"] and passwd== user_dic["passwd"]:
                    current_dic["username"]=username
                    current_dic["login"]=True
                    res=func(*args,**kwargs)
                    return res
            else:
                print("用户名或密码错误")
        return foo
    
    @fangfa
    def zhuye(*args,**kwargs):
        print("欢迎来到京东主页")
    
    @fangfa
    def home(name):
        print("%s欢迎回来" %name)
    
    @fangfa
    def shopping_car(name,m1,m2,m3):
        print("%s的购物车有[%s],[%s],[%s]" %(name,m1,m2,m3))
    
    zhuye()
    home("sb")
    shopping_car("sb","奶茶","可乐","巧克力")
    View Code

    闭包(加上验证类型):最终版本

    user_list=[{"username":"alex","passwd":"123"},{"username":"sb","passwd":"abc"},{"username":"baby","passwd":"456"}]
    current_dic={"username":None,"login":False}
    def total(user_type):       ##闭包,函数最终运行的还是foo
        def fangfa(func):
            def foo(*args,**kwargs):
                if user_type == "ldap":
                    print("认证类型%s" %user_type)
    
                    if current_dic["username"] and current_dic["login"]:
                        res=func(*args,**kwargs)
                        return res
    
                    username=input("用户名:").strip()
                    passwd=input("密码:").strip()
                    for user_dic in user_list:
                        if username== user_dic["username"] and passwd== user_dic["passwd"]:
                            current_dic["username"]=username
                            current_dic["login"]=True
                            res=func(*args,**kwargs)
                            return res
    
                    else:
                        print("用户名或密码错误")
                        return
                elif user_list == "aaa":
                    print("验证类型%s" %user_type)
                    res=func(*args,**kwargs)
                    return res
                else:
                    print("用户验证类型%s错误" %user_type)
                    res=func(*args,**kwargs)
                    return res
    
    
            return foo
        return fangfa
    @total(user_type="ldap")
    def zhuye(*args,**kwargs):
        print("欢迎来到京东主页")
    
    @total(user_type="aaa")
    def home(name):
        print("%s欢迎回来" %name)
    
    @total(user_type="dasjdk")
    def shopping_car(name,m1,m2,m3):
        print("%s的购物车有[%s],[%s],[%s]" %(name,m1,m2,m3))
    
    zhuye()
    home("sb")
    shopping_car("sb","奶茶","可乐","巧克力")
    View Code
  • 相关阅读:
    深入浅出MFC——MFC六大关键技术仿真(二)
    错误:Invalid action class configuration that references an unknown class named [XXX]的解决
    错误:java.lang.NoClassDefFoundError: com/project/common/exception/ServiceException 的解决
    SQL查询语句优化的实用方法
    ueditor表格边框没有颜色的解决
    ueditor显示内容末尾有多余标记的解决
    form表单中enctype属性作用
    springMVC中@RequestParam和@RequestBody注解的用法
    错误:This function has none of DETERMINISTIC... 的解决
    如何区分内存类型及查看内存的兼容性
  • 原文地址:https://www.cnblogs.com/sakura-gyt/p/12788232.html
Copyright © 2020-2023  润新知