zoukankan      html  css  js  c++  java
  • 【Python基础】装饰器

    详解Python装饰器

    阅读目录

    一、什么是装饰器

    器即函数

    装饰即修饰,意指为其他函数添加新功能

    装饰器定义:本质就是函数,功能是为其他函数添加新功能

    二 、装饰器需要遵循的原则

    1、不修改被装饰函数的源代码(开放封闭原则)

    2、为被装饰函数添加新功能后,不修改被修饰函数的调用方式

    三、实现装饰器知识储备

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

    四、高阶函数

    高阶函数定义:

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

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

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

    def foo():
        print('我的函数名作为参数传给高阶函数')
    def gao_jie1(func):
        print('我就是高阶函数1,我接收的参数名是%s' %func)
        func()
    
    def gao_jie2(func):
        print('我就是高阶函数2,我的返回值是%s' %func)
        return func
    
    gao_jie1(foo)
    gao_jie2(foo)
    高阶函数示范
    #高阶函数应用1:把函数当做参数传给高阶函数
    import time
    def foo():
        print('from the foo')
    
    def timmer(func):
        start_time=time.time()
        func()
        stop_time=time.time()
        print('函数%s 运行时间是%s' %(func,stop_time-start_time))
    timmer(foo)
    #总结:我们确实为函数foo增加了foo运行时间的功能,但是foo原来的执行方式是foo(),现在我们需要调用高阶函数timmer(foo),改变了函数的调用方式
    把函数当做参数传给高阶函数
    #高阶函数应用2:把函数名当做参数传给高阶函数,高阶函数直接返回函数名
    import time
    def foo():
        print('from the foo')
    
    def timmer(func):
        start_time=time.time()
        return func
        stop_time=time.time()
        print('函数%s 运行时间是%s' %(func,stop_time-start_time))
    foo=timmer(foo)
    foo()
    #总结:我们确实没有改变foo的调用方式,但是我们也没有为foo增加任何新功能
    函数返回值是函数名

    高阶函数总结

    1.函数接收的参数是一个函数名
      作用:在不修改函数源代码的前提下,为函数添加新功能,
      不足:会改变函数的调用方式
    2.函数的返回值是一个函数名
      作用:不修改函数的调用方式
      不足:不能添加新功能

    五、函数嵌套

    def father(name):
        print('from father %s' %name)
        def son():
            print('from son')
            def grandson():
                print('from grandson')
            grandson()
        son()
    
    father('熊大')
    
    #在father 函数里面再定义son 函数 叫做函数嵌套
    # def father(name):
    #     print('from father %s' %name)
    #     def son():
    #         print('from son')
    #     print(locals())     #打印当前层的局部变量
    #
    # father('xiong')
    
    def father(name):
        # print('from father %s' %name)
        def son():
            print('我的爸爸是%s'%name)
            def grandson():
                name = "我自己"
                print('我的爷爷是%s'%name)
            grandson()
        son()
    
    father('xiong')
    嵌套练习1

    六、闭包

    '''
    闭包:在一个作用域里放入定义变量,相当于打了一个包
    '''
    def father(name):
        def son():
            # name='alex'
            print('我爸爸是 [%s]' %name)
            def grandson():
                name='熊大'
                print('我爷爷是 [%s]' %name)
            grandson()
        son()
    
    father('灰太狼')

    七、无参装饰器

    无参装饰器=高级函数+函数嵌套

    基本框架

    #这是实现一个装饰器最基本的框架
    def timer(func):
         def wrapper():
             func()
         return wrapper

    加上参数

    def timer(func):
         def wrapper(*args,**kwargs):
             func(*args,**kwargs)
         return wrapper

    加上功能

    #这是计算函数运行时间的装饰功能
    import time
    def timer(func):
        def wrapper(*args,**kwargs):
            start_time=time.time()
            func(*args,**kwargs)
            stop_time=time.time()
            print('函数[%s],运行时间是[%s]' %(func,stop_time-start_time))
        return wrapper

    加上返回值 (wrapper() 函数加上return)

    import time
    def timer(func):
        def wrapper(*args,**kwargs):
            start_time=time.time()
            res=func(*args,**kwargs)
            stop_time=time.time()
            print('函数[%s],运行时间是[%s]' %(func,stop_time-start_time))
            return res
        return wrapper

    使用装饰器

    def cal(array):
        res=0
        for i in array:
            res+=i
        return res
    
    cal=timer(cal)
    cal(range(10))

    语法糖 @

    @timer  #@timer <===> cal=timer(cal)
    def cal(array):
        res=0
        for i in array:
            res+=i
        return res
    
    cal(range(10))

    代码运行过程:

     

    import time
    def timmer(func): #func=test1
        def wrapper(*args,**kwargs): #test('linhaifeng',age=18)  args=('linhaifeng')  kwargs={'age':18}
            start_time=time.time()
            res=func(*args,**kwargs) #就是在运行test()         func(*('linhaifeng'),**{'age':18})
            stop_time = time.time()
            print('运行时间是%s' %(stop_time-start_time))
            return res
        return wrapper
    
    
    def test(name,age):
        time.sleep(3)
        print('test函数运行完毕,名字是【%s】 年龄是【%s】' %(name,age))
        return '这是test的返回值'
    
    test=timmer(test)
    res=test('linhaifeng',age=18)  #就是在运行wrapper('linhaifeng',age=18)
    print(res)
    
    @timmer     # ===> test=timmer(test)
    def test1(name,age,gender):
        time.sleep(1)
        print('test1函数运行完毕,名字是【%s】 年龄是【%s】 性别【%s】' %(name,age,gender))
        return '这是test1的返回值'
    
    res = test1('alex',18,'male')
    print(res)

    补充:*args,**kwargs 传值

    def test2(name,age,gender): #test2(*('alex',18,'male','x','y'),**{})
        #name,age,gender=('alex',18,'male','x','y')
        print(name)
        print(age)
        print(gender)
    
    def test1(*args,**kwargs):
        print(args)
        print(kwargs)
        test2(*args,**kwargs)
    
    # test2('alex',18,gender='male')
    
    test1('alex',18,'male')     #test2(*('alex',18,'male'),**{})
    test1('alex',18,gender = 'male')    #test2(*('alex',18),**{"gender":'male'})
    *args,**kwargs 传值

    八、装饰器应用示例

    import time
    user_info = [
        {"name":"灰太狼",'passwd':"123"},
        {"name":"喜洋洋",'passwd':'456'},
        {"name":"红太狼",'passwd':'789'},
        {"name":"小灰灰",'passwd':'000'},
        {"name":"美羊羊",'passwd':'1314'},
        {"name":"懒洋洋",'passwd':'159'},
    ]
    current_state = {"username":None,"login":False}
    
    def auth_func(func):
        def wrapper(*args,**kwargs):
            if current_state["username"] and current_state["login"]:
                res = func(*args,**kwargs)
                return res
            username = input("输入用户名>>>")
            passwd = input("输入密码>>>")
            for item in user_info:
                if username == item["name"] and passwd == item["passwd"]:
                    current_state["username"] = username
                    current_state["login"] = True
                    res = func(*args, **kwargs)
                    return res
            else:
                print("输入的用户名或密码错误,请重新输入!")
        return wrapper
    
    @auth_func  #--->index = auth_func(index)
    def index():
        print('开始执行index()函数')
        time.sleep(1)
        print("欢迎来到京东主页面。。。")
    
    @auth_func
    def home(name):
        print('开始执行home()函数')
        time.sleep(1)
        print("你好啊%s,欢迎回家!"%name)
    
    @auth_func
    def shopping_car(name,goods):
        print('开始执行shopping_car()函数')
        time.sleep(2)
        print("%s的购物车里面有商品%s"%(name,goods))
    
    index()
    home("村长")
    shopping_car("灰太狼",['牛奶','饼干','羊腿'])
    
    
    ####打印结果
    输入用户名>>>喜洋洋
    输入密码>>>456
    开始执行index()函数
    欢迎来到京东主页面。。。
    开始执行home()函数
    你好啊村长,欢迎回家!
    开始执行shopping_car()函数
    灰太狼的购物车里面有商品['牛奶', '饼干', '羊腿']
    无参装饰器-综合案例
    import time
    f = open("filedb",'r+',encoding="utf8")
    userInfo = f.readlines()
    f.close()
    current_state = {"username":None,"login":False}
    def auth(auth_type = "filedb"):
        def auth_func(func):
            def wrapper(*args,**kwargs):
                if current_state["username"] and current_state["login"]:
                    res = func(*args,**kwargs)
                    return res
                username = input("输入用户名>>>")
                passwd = input("输入密码>>>")
                for item in userInfo:
                    if username == eval(item)['name'] and passwd == eval(item)['passwd']:
                        current_state["username"] = username
                        current_state["login"] = True
                        res = func(*args, **kwargs)
                        return res
                else:
                    print("输入的用户名或密码错误,请重新输入!")
            return wrapper
        return auth_func
    
    @auth(auth_type="filedb")  #@auth(auth_type="filedb")--->auth_func 附加了一个auth_type参数 --->index=auth_func(index)
    def index():
        print('开始执行index()函数')
        time.sleep(1)
        print("欢迎来到京东主页面。。。")
    
    @auth(auth_type="filedb")
    def home(name):
        print('开始执行home()函数')
        time.sleep(1)
        print("你好啊%s,欢迎回家!"%name)
    
    @auth(auth_type="filedb")
    def shopping_car(name,goods):
        print('开始执行shopping_car()函数')
        time.sleep(2)
        print("%s的购物车里面有商品%s"%(name,goods))
    
    index()
    home("村长")
    shopping_car("灰太狼",['牛奶','饼干','羊腿'])
    有参数装饰器-验证功能
    {"name":"灰太狼",'passwd':"123"}
    {"name":"喜洋洋",'passwd':'456'}
    {"name":"红太狼",'passwd':'789'}
    {"name":"小灰灰",'passwd':'000'}
    {"name":"美羊羊",'passwd':'1314'}
    {"name":"懒洋洋",'passwd':'159'}
    有参数装饰器-filedb文件

    九、超时装饰器

    十、Python内置的装饰器

    链接: 静态属性(@property)、类方法(@classmethod)、静态方法(@staticmethod)

    参考:

    https://www.cnblogs.com/linhaifeng/articles/6140395.html#_label8

  • 相关阅读:
    php上传进度条
    array_combine — 创建一个数组,用一个数组的值作为其键名,另一个数组的值作为其值
    password_hash 与 password_verify
    这是一个微信带参数的二维码,自定义菜单,与图文回复
    go to 语句用起来还是挺方便的
    初次使用海豚php的一个例子
    图片下载
    一对一的关联映射
    延迟加载
    proxy和proxy-no的策略取值区别
  • 原文地址:https://www.cnblogs.com/XJT2018/p/10861241.html
Copyright © 2011-2022 走看看