zoukankan      html  css  js  c++  java
  • python基础-装饰器

    一、什么是装饰器

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

    二、装饰器遵循的原则

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

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

    三、实现装饰器的知识储备

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

    示例1: 用函数实现

     1 #计算从1-100,统计函数运行时间
     2 
     3 import time
     4 def cal(l):
     5     start_time=time.time()
     6     res=0
     7     for i in l:
     8         time.sleep(0.1)
     9         res+=i
    10     stop_time = time.time()
    11     print('函数的运行时间是%s' %(stop_time-start_time))
    12     return res
    13 
    14 print(cal(range(100)))   #直接打印得到运行的时间

    执行结果:

    1 函数的运行时间是10.007169723510742
    2 4950

    示例2:用装饰器实现函数运行时间

     1 import time
     2 def timmer(func):
     3     def wrapper(*args,**kwargs):
     4         start_time=time.time()
     5         res=func(*args,**kwargs)
     6         stop_time = time.time()
     7         print('函数运行时间是%s' %(stop_time-start_time))
     8         return res
     9     return wrapper
    10 
    11 @timmer   #调用装饰器
    12 def cal(l):
    13     res=0
    14     for i in l:
    15         time.sleep(0.1)
    16         res+=i
    17     return res
    18 
    19 res=cal(range(20))
    20 print(res)

    四、高阶函数高阶函数定义

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

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

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

    高阶函数示例如下:

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

     1 #1.函数接收的参数是一个函数名
     2 import time
     3 def foo():
     4     time.sleep(3)
     5     print('你好啊林师傅')
     6 
     7 def test(func):    #test高阶函数
     8     # print(func)  #获取到内存地址
     9     start_time=time.time()
    10     func()
    11     stop_time = time.time()
    12     print('函数运行时间是  %s' % (stop_time-start_time))
    13 # foo()
    14 test(foo)

    执行结果:

    1 你好啊林师傅
    2 函数运行时间是  3.0003013610839844
    3 来自foo

    示例2

     1 def foo():
     2     print('from the foo')
     3 def test(func):
     4     return func
     5 
     6 # res=test(foo)
     7 # # print(res)
     8 # res()
     9 
    10 foo=test(foo)
    11 # # print(res)
    12 foo()
    13 
    14 import time
    15 def foo():
    16     time.sleep(3)
    17     print('来自foo')
    18 
    19 #不修改foo源代码
    20 #不修改foo调用方式

    示例3:

     1 #多运行了一次,不合格
     2 import time
     3 def foo():
     4     time.sleep(3)
     5     print('来自foo')
     6 
     7 def timer(func):
     8     start_time=time.time()
     9     func()
    10     stop_time = time.time()
    11     print('函数运行时间是  %s' % (stop_time-start_time))
    12     return func
    13 foo=timer(foo)
    14 foo()

    示例4:

     1 #没有修改被修饰函数的源代码,也没有修改被修饰函数的调用方式,但是也没有为被修饰函数添加新功能
     2 import time
     3 def foo():
     4     time.sleep(3)
     5     print('来自foo')
     6 
     7 def timer(func):
     8     start_time=time.time()
     9     return func
    10     stop_time = time.time()
    11     print('函数运行时间是  %s' % (stop_time-start_time))
    12 
    13 foo=timer(foo)
    14 foo()

    执行结果:

    1 来自foo

    结论:高阶函数,满足不了装饰器的功能。

    高阶函数总结:

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

    2.函数的返回值是一个函数名
      作用:不修改函数的调用方式
      不足:不能添加新功能

    五、函数的嵌套

    1、什么是函数的嵌套?

        通过在函数内部def的关键字再声明一个函数即为嵌套

    示例:

    1 def father(name):
    2     def son():
    3         print('我的爸爸是%s' %name)
    4         def grandson():
    5             name='就是我自己'
    6             print('我的爷爷是%s' %name)
    7         grandson()
    8     son()
    9 father('linhaifeng')

    执行结果:

    1 我的爸爸是linhaifeng
    2 
    3 我的爷爷是就是我自己

    六、闭包

     1 #闭包:在一个作用域里放入定义变量,相当于打了一个包
     2 def father(auth_type):
     3     # print('from father %s' %name)
     4     def son():
     5         # name='linhaifeng_1'
     6         # print('我的爸爸是%s' %name)
     7         def grandson():
     8             print('我的爷爷是%s' %auth_type)
     9         grandson()
    10     # print(locals())
    11     son()
    12 # father('linhaifeng')
    13 father('filedb')

    执行结果:

    1 我的爷爷是filedb

    七、无参装饰器

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

    1、基本框架

    1 #这就是一个实现一个装饰器最基本的架子
    2 def timer(func):
    3     def wrapper():
    4         func()
    5 
    6     return wrapper

    2、基本装饰器(基本框架+参数+功能+返回值+使用装饰器+语法糖@)

    import time
    
    def timmer(func): #func=test
        def wrapper():
            # print(func)
            start_time=time.time()
            func() #就是在运行test()
            stop_time = time.time()
            print('运行时间是%s' %(stop_time-start_time))
        return wrapper
    
    @timmer #test=timmer(test)  #在函数名前面加个@ ,这就是语法糖
    def test():
        time.sleep(3)
        print('test函数运行完毕')
    
    test()

    代码说明:

    1 # res=timmer(test)  #返回的是wrapper的地址
    2 # res()  #执行的是wrapper()
    3 #
    4 # test=timmer(test)  #返回的是wrapper的地址
    5 # test()  #执行的是wrapper()
    6 #
    7 #  @timmer  就相当于 test=timmer(test)
    View Code

    执行结果:

    1 test函数运行完毕
    2 运行时间是3.000155210494995

    3、加上返回值

     1 import time
     2 def timmer(func): #func=test
     3     def wrapper():
     4         start_time=time.time()
     5         res=func() #就是在运行test()
     6         stop_time = time.time()
     7         print('运行时间是%s' %(stop_time-start_time))
     8         return res
     9     return wrapper
    10 
    11 @timmer #test=timmer(test)
    12 def test():
    13     time.sleep(3)
    14     print('test函数运行完毕')
    15     return '这是test的返回值'
    16 
    17 res=test()  #就是在运行wrapper
    18 print(res)

    执行结果:

    1 test函数运行完毕
    2 运行时间是3.0001416206359863
    3 这是test的返回值

    4、加上参数

     1 import time
     2 def timmer(func): #func=test1
     3     def wrapper(*args,**kwargs): #test('linhaifeng',age=18)  args=('linhaifeng')  kwargs={'age':18}
     4         start_time=time.time()
     5         res=func(*args,**kwargs) #就是在运行test()         func(*('linhaifeng'),**{'age':18})
     6         stop_time = time.time()
     7         print('运行时间是%s' %(stop_time-start_time))
     8         return res
     9     return wrapper
    10 
    11 # @timmer #test=timmer(test)
    12 def test(name,age):
    13     time.sleep(3)
    14     print('test函数运行完毕,名字是【%s】 年龄是【%s】' %(name,age))
    15     return '这是test的返回值'
    16 
    17 @timmer
    18 def test1(name,age,gender):
    19     time.sleep(1)
    20     print('test1函数运行完毕,名字是【%s】 年龄是【%s】 性别【%s】' %(name,age,gender))
    21     return '这是test的返回值'
    22 
    23 # res=test('linhaifeng',age=18)  #就是在运行wrapper
    24 # # print(res)
    25 # test1('alex',18,'male')
    26 
    27 test1('alex',18,'male')

    执行结果:

    1 test1函数运行完毕,名字是【alex】 年龄是【18】 性别【male】
    2 运行时间是1.0007386207580566

    八、装饰器应用案例

    写一个模拟京东网站,用户认证登录网站和购物加入购物车功能程序

    实现功能:用装饰器给所有函数加上验证功能

    1、基本框架

     1 def index():
     2     pass
     3 
     4 def home():
     5     pass
     6 
     7 def shopping_car()
     8     pass
     9 
    10 def order()
    11     pass

    2、开始实现

    示例1:没有判断验证方式,直接就显示购物车结果。

     1 user_list=[
     2     {'name':'alex','passwd':'123'},
     3     {'name':'linhaifeng','passwd':'123'},
     4     {'name':'wupeiqi','passwd':'123'},
     5     {'name':'yuanhao','passwd':'123'},
     6 ]
     7 current_dic={'username':None,'login':False}
     8 
     9 def auth(auth_type='filedb'):
    10     def auth_func(func):
    11         def wrapper(*args,**kwargs):
    12             print('认证类型是',auth_type)
    13             if auth_type == 'filedb':
    14                 if current_dic['username'] and current_dic['login']:
    15                     res = func(*args, **kwargs)
    16                     return res
    17                 username=input('用户名:').strip()
    18                 passwd=input('密码:').strip()
    19                 for user_dic in user_list:
    20                     if username == user_dic['name'] and passwd == user_dic['passwd']:
    21                         current_dic['username']=username
    22                         current_dic['login']=True
    23                         res = func(*args, **kwargs)
    24                         return res
    25                 else:
    26                     print('用户名或者密码错误')
    27             elif auth_type == 'ldap':
    28                 print('鬼才特么会玩')
    29                 res = func(*args, **kwargs)
    30                 return res
    31             else:
    32                 print('鬼才知道你用的什么认证方式')
    33                 res = func(*args, **kwargs)
    34                 return res
    35 
    36         return wrapper
    37     return auth_func
    38 
    39 @auth(auth_type='filedb') #auth_func=auth(auth_type='filedb')-->@auth_func 附加了一个auth_type  --->index=auth_func(index)
    40 def index():
    41     print('欢迎来到京东主页')
    42 
    43 @auth(auth_type='ldap')
    44 def home(name):
    45     print('欢迎回家%s' %name)
    46 #
    47 @auth(auth_type='sssssss')
    48 def shopping_car(name):
    49     print('%s的购物车里有[%s,%s,%s]' %(name,'奶茶','妹妹','娃娃'))
    50 
    51 # print('before-->',current_dic)
    52 # index()
    53 # print('after--->',current_dic)
    54 # home('产品经理')
    55 shopping_car('产品经理')

    执行结果:

    1 认证类型是 sssssss
    2 鬼才知道你用的什么认证方式
    3 产品经理的购物车里有[奶茶,妹妹,娃娃]

    示例2 :给他加上验证功能装饰器(判断用户和密码,跟字典里的用户和密码进行比对)

     1 user_list=[
     2     {'name':'alex','passwd':'123'},
     3     {'name':'linhaifeng','passwd':'123'},
     4     {'name':'wupeiqi','passwd':'123'},
     5     {'name':'yuanhao','passwd':'123'},
     6 ]
     7 current_dic={'username':None,'login':False}
     8 
     9 
    10 def auth_func(func):
    11     def wrapper(*args,**kwargs):
    12         if current_dic['username'] and current_dic['login']:
    13             res = func(*args, **kwargs)
    14             return res
    15         username=input('用户名:').strip()
    16         passwd=input('密码:').strip()
    17         for user_dic in user_list:
    18             if username == user_dic['name'] and passwd == user_dic['passwd']:
    19                 current_dic['username']=username
    20                 current_dic['login']=True
    21                 res = func(*args, **kwargs)
    22                 return res  #返回值
    23         else:
    24             print('用户名或者密码错误')
    25 
    26     return wrapper
    27 
    28 @auth_func     #加证功能,也是装饰器
    29 def index():
    30     print('欢迎来到京东主页')
    31 
    32 @auth_func
    33 def home(name):
    34     print('欢迎回家%s' %name)
    35 
    36 @auth_func
    37 def shopping_car(name):
    38     print('%s的购物车里有[%s,%s,%s]' %(name,'奶茶','妹妹','娃娃'))
    39 
    40 print('before-->',current_dic)
    41 index()
    42 print('after--->',current_dic)
    43 home('产品经理')
    44 shopping_car('产品经理')

    执行结果:

    1 before--> {'username': None, 'login': False}
    2 用户名:alex          #输入字典里的用户名和密码,才能登录成功。
    3 密码:123
    4 欢迎来到京东主页
    5 after---> {'username': 'alex', 'login': True}
    6 欢迎回家产品经理
    7 产品经理的购物车里有[奶茶,妹妹,娃娃]
  • 相关阅读:
    30天内自动登录
    本地保存cookie
    thymeleaf 基本表达式
    适配器(adapter)与fragment之间、fragment与activity之间的通信问题
    String/Stringbuilder/StringBuffer
    if else与switch for与foreach
    iOS App 签名的原理
    iOS category内部实现原理
    iOS中的事件的产生和传递
    RunLoop
  • 原文地址:https://www.cnblogs.com/nulige/p/6144267.html
Copyright © 2011-2022 走看看