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}
    
  • 相关阅读:
    Power BI 根据用户权限动态生成导航跳转目标
    Power BI Tooltips 增强功能
    Power BI refresh error “could not load file or assembly…provided impersonation level is invalid”
    SQL 错误代码 18456
    如何使用SQL Server Integration Services从多个Excel文件读取数据
    通过表格编辑器将现有表引入Power BI数据流
    Power BI 中动态增长的柱状图
    ambari2.7.3离线安装hdp3.1.0时,ambari-hdp-1.repo中baseurl无值
    ambari 安装 cannot download file mysql-connector-java from http://8080/resource/mysql-connector-java.jar
    洛谷P4180 [BJWC2010]严格次小生成树
  • 原文地址:https://www.cnblogs.com/lsf123456/p/11180815.html
Copyright © 2011-2022 走看看