python基础-装饰器

寵の児 提交于 2019-12-24 13:08:07

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)

执行结果:

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 产品经理的购物车里有[奶茶,妹妹,娃娃]

 

一、什么是装饰器

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

 

二、装饰器遵循的原则

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)

执行结果:

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 产品经理的购物车里有[奶茶,妹妹,娃娃]

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!