• Python-装饰器


    一、什么是装饰器:

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

    二、装饰器遵循的原则:

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

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

    三、实现函数装饰器知识储备

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

      示例:有修饰器和没有修饰器的区别:

     1 ## 常规方法实现
     2 import time
     3 
     4 def cal(l):
     5     startTime = time.time()
     6     red = 0
     7     for i in l:
     8         time.sleep(0.1)
     9         red += i
    10     stopTime = time.time()
    11     print("函数运行时间: %s" %(startTime-stopTime))
    12     return red
    13 
    14 print(cal(range(100)))
    15 
    16 
    17 -------------------------------------------------------------------------
    18 ## 使用修饰器实现
    19 import time
    20 
    21 def timer(func):
    22     def wrapper(*args,**kwargs):
    23         startTime = time.time()
    24         red = func(*args,**kwargs)
    25         stopTime = time.time()
    26         print("函数运行时间:%s" %(startTime-stopTime))
    27         return red
    28     return wrapper
    29 
    30 @timer
    31 def cal(l):
    32     red = 0
    33     for i in l:
    34         time.sleep(0.1)
    35         red += i
    36     return red
    37 
    38 print(cal(range(10)))

     四、高阶函数的定义:(查看 http://www.cnblogs.com/JerryZao/p/8605019.html)

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

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

      以上满足一个即可称为高阶函数

    五、函数嵌套

      1、什么是函数嵌套

        函数嵌套是在函数的内部重新定义一个新的函数,而不是调用一个函数

    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('xxxx')

    六、闭包

     1 '''
     2 闭包:在一个作用域里放入定义变量,相当于打了一个包
     3 '''
     4 def father(name):
     5     def son():
     6         # name='alex'
     7         print('我爸爸是 [%s]' %name)
     8         def grandson():
     9             # name='wupeiqi'
    10             print('我爷爷是 [%s]' %name)
    11         grandson()
    12     son()
    13 
    14 father('xxxx')
     1 ## 再举个例子
     2 def line_conf(a, b):
     3     def line(x):
     4         return b*x + a
     5 
     6     return line
     7 
     8 line_conf(1,2)
     9 
    10 # 我们可以看到,只要环境变量a,b 的值定了,那么line函数的表达式也就定了,只取决于自己的函数参数

    七、无参数修饰器

      无参修饰器 = 高阶函数 + 函数嵌套

      1、基本框架

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

      2、加上参数

    1 def timer(func):
    2     def wrapper(*args,**kwargs):
    3         func(*args,**kwargs)
    4     return wrapper

      3、加上功能

    1 import time
    2 def timer(func):
    3     def wrapper(*args,**kwargs):
    4         start_time=time.time()
    5         func(*args,**kwargs)
    6         stop_time=time.time()
    7         print('函数[%s],运行时间是[%s]' %(func,stop_time-start_time))
    8     return wrapper

      4、加上返回值

    1 import time
    2 def timer(func):
    3     def wrapper(*args,**kwargs):
    4         start_time=time.time()
    5         res=func(*args,**kwargs)
    6         stop_time=time.time()
    7         print('函数[%s],运行时间是[%s]' %(func,stop_time-start_time))
    8         return res
    9     return wrapper

      5、使用装饰器

    1 def cal(array):
    2     res=0
    3     for i in array:
    4         res+=i
    5     return res
    6 
    7 cal=timer(cal)
    8 cal(range(10))

      6、语法糖 @

    1 @timer  #@timer就等同于cal=timer(cal)   cal就是wrapper  ,cal()就是执行wrapper()函数
    2 def cal(array):
    3     res=0
    4     for i in array:
    5         res+=i
    6     return res
    7 
    8 cal(range(10))

      分析示例 

     1 import time
     2 def timmer(func): #func=test1
     3     def wrapper(*args,**kwargs): #test('linhaifeng',age=18)  args=('linhaifeng')  kwargs={'age':18} 将参数完整的传给func
     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')

    八、装饰器应用案例:

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

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

      示例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 user_list=[
     2     {'name':'alex','passwd':'123'},
     3     {'name':'linhaifeng','passwd':'123'},
     4     {'name':'wupeiqi','passwd':'123'},
     5     {'name':'yuanhao','passwd':'123'},
     6 ]
     7 
     8 current_user={'username':None,'login':False}
     9 
    10 def auth_deco(func):
    11     def wrapper(*args,**kwargs):
    12         if current_user['username'] and current_user['login']:
    13             res=func(*args,**kwargs)
    14             return res
    15         username=input('用户名: ').strip()
    16         passwd=input('密码: ').strip()
    17 
    18         for index,user_dic in enumerate(user_list):
    19             if username == user_dic['name'] and passwd == user_dic['passwd']:
    20                 current_user['username']=username
    21 
    22                 current_user['login']=True
    23                 res=func(*args,**kwargs)
    24                 return res
    25                 break
    26         else:
    27             print('用户名或者密码错误,重新登录')
    28 
    29     return wrapper
    30 
    31 @auth_deco
    32 def index():
    33     print('欢迎来到主页面')
    34 
    35 @auth_deco
    36 def home():
    37     print('这里是你家')
    38 
    39 def shopping_car():
    40     print('查看购物车啊亲')
    41 
    42 def order():
    43     print('查看订单啊亲')
    44 
    45 print(user_list)
    46 # index()
    47 print(user_list)
    48 home()
    49 
    50 无参装饰器
    无参数(语法糖)
     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 
     8 current_user={'username':None,'login':False}
     9 def auth(auth_type='file'):
    10     def auth_deco(func):
    11         def wrapper(*args,**kwargs):
    12             if auth_type == 'file':
    13                 if current_user['username'] and current_user['login']:
    14                     res=func(*args,**kwargs)
    15                     return res
    16                 username=input('用户名: ').strip()
    17                 passwd=input('密码: ').strip()
    18 
    19                 for index,user_dic in enumerate(user_list):
    20                     if username == user_dic['name'] and passwd == user_dic['passwd']:
    21                         current_user['username']=username
    22                         current_user['login']=True
    23                         res=func(*args,**kwargs)
    24                         return res
    25                         break
    26                 else:
    27                     print('用户名或者密码错误,重新登录')
    28             elif auth_type == 'ldap':
    29                 print('巴拉巴拉小魔仙')
    30                 res=func(*args,**kwargs)
    31                 return res
    32         return wrapper
    33     return auth_deco
    34 
    35 
    36 #auth(auth_type='file')就是在运行一个函数,然后返回auth_deco,所以@auth(auth_type='file')
    37 #就相当于@auth_deco,只不过现在,我们的auth_deco作为一个闭包的应用,外层的包auth给它留了一个auth_type='file'参数
    38 @auth(auth_type='ldap')
    39 def index():
    40     print('欢迎来到主页面')
    41 
    42 @auth(auth_type='ldap')
    43 def home():
    44     print('这里是你家')
    45 
    46 def shopping_car():
    47     print('查看购物车啊亲')
    48 
    49 def order():
    50     print('查看订单啊亲')
    51 
    52 # print(user_list)
    53 index()
    54 # print(user_list)
    55 home()
    56 
    57 带参装饰器
    含有参数

    九、补充:

      解压序列

     1 a,b,c = [1,2,3]
     2 
     3 --->
     4 
     5 a=1
     6 b=2
     7 c=3
     8 
     9 
    10 s = [1,2,3,5,6,7,8,8,9,0,0,32,453,5435,23,5,675,6]
    11 a,*_,b = s
    12 print(a) # 1
    13 print(b) # 6

      值交换

    1 a = 1
    2 b = 2
    3 
    4 ----->
    5 
    6 a,b = b,a
    7 
    8 # 这样就ab的值交换了

      

    为什么要坚持,想一想当初!
  • 相关阅读:
    Web 前端 UI 组件库文档自动化方案 All In One
    how to auto open demo and create it in a new codesandbox
    TypeScript & Canvas 实现可视化白板
    2020~2021 职业规划书
    PostCSS All In One
    zsh terminal set infinity scroll height
    npm version ^ meaning
    vue-cli & webpack & vue.config.js
    [HDOJ5350]MZL's munhaff function
    [POJ3061]Subsequence
  • 原文地址:https://www.cnblogs.com/JerryZao/p/8645266.html
Copyright © 2020-2023  润新知