zoukankan      html  css  js  c++  java
  • 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}
    
  • 相关阅读:
    Zebra命令模式分析(一)  分析
    sublime text2
    开源路由软件zebra的命令存储原理及使用方法
    开源路由软件zebra介绍和和在Linux环境下的安装
    jQuery删除节点
    如何成为一名软件架构师
    jQuery中的DOM操作
    编写自己的Shell解释器
    Notepad++集成VC2010环境
    ffmpeg使用语法
  • 原文地址:https://www.cnblogs.com/lsf123456/p/11180815.html
Copyright © 2011-2022 走看看