Python-12-装饰器

一、定义

器即函数

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

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

原则:

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

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

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

1. 高阶函数

默认满足以下两个条件中的一个就是高阶函数:

  • 函数的传入参数是一个函数名
  • 函数的返回值是一个函数名
#高阶函数应用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增加任何新功能

函数返回值是函数名

2. 函数嵌套

在函数内部定义函数

3. 闭包

闭包:在一个作用域里放入定义变量,相当于打了一个包

三、装饰器实现

def timmer(func):
    def wrapper(*args, **kwargs):
        print(func)
        res = func(*args, **kwargs)
        return res

    return wrapper

@timmer  # test = timmer(test)
def test(name, age):
    print('姓名:%s,年龄:%s' % (name, age))
    return 1

msg = test('Tom', 18)  # 就是在运行wrapper
print(msg)

四、应用

 网站登录认证

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

五、类的装饰器

装饰器不仅可以对函数进行装饰,还可以装饰类

def deco(obj):
    print('====')
    obj.x = 1
    obj.y = 2
    return obj

@deco
class Foo(object):
    pass

print(Foo.__dict__)  
# {'__module__': '__main__', '__dict__': <attribute '__dict__' of 'Foo' objects>, 
# '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None, 'x': 1, 'y': 2}

 

posted @ 2019-07-13 15:35  lsf123456  阅读(252)  评论(0编辑  收藏  举报