• Python--装饰器


    一、什么是装饰器

      解释:

        器即函数

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

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

    二、装饰器需要遵循的原则

      原则:

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

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

    三、实现装饰器知识储备

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

    四、高阶函数

      高阶函数的定义:

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

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

        3、满足上述条件任意一个,都可称之为高阶函数

     1 def foo():
     2     print('我的函数名作为参数传给高阶函数')
     3 
     4 def gaojie1(func):
     5     print('我就是高阶函数1,我接收的参数名为%s'%func)
     6     func()
     7 
     8 def gaojie2(func):
     9     print('我就是高阶函数2,我的返回值是%s'%func)
    10     return func
    11 
    12 gaojie1(foo)
    13 gaojie2(foo)

    输出结果:

    1 我就是高阶函数1,我接收的参数名为<function foo at 0x0000000002081EA0>
    2 我的函数名作为参数传给高阶函数
    3 我就是高阶函数2,我的返回值是<function foo at 0x0000000002081EA0>

    应用一:把函数作为参数传递给高阶函数

     1 # 高阶函数的应用1:把函数作为参数传给高阶函数
     2 import time
     3 def foo():
     4     print('from the foo')
     5 
     6 def timmer(func):
     7     start_time=time.time()
     8     time.sleep(1)
     9     func()
    10     stop_time=time.time()
    11     print('函数%s,运行时间是%s'%(func,stop_time-start_time))
    12 
    13 timmer(foo)
    14 #总结:我们确实为函数foo增加了foo运行时间的功能,但是foo原来的
    15 #执行方式是foo(),现在我们需要高阶函数timmer(foo),改变了函数的
    16 #调用方式

      应用二:把函数名当做参数传递给高阶函数,高阶函数直接返回函数名

     1 #高阶函数应用2:把函数名当做参数传给高阶函数,高阶函数直接返回函数名
     2 import time
     3 def foo():
     4     print('from the foo')
     5 
     6 def timmer(func):
     7     start_time=time.time()
     8     return func
     9     stop_time=time.time()
    10     print('函数%s运行时间是%s'%(func,stop_time-start_time))
    11 foo=timmer(foo)
    12 foo()
    13 #总结:我们确实没有改变foo的调用方式,但是我们也没有为foo增加任何功能

    高阶函数总结:

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

        作用:在不修改函数源代码的前提下,为函数添加新功能

        不足:会改变函数的调用方式

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

        作用:不修改函数的调用方式

        不足:不能添加新的功能

    五、函数嵌套

      描述:在函数内部定义函数

      代码:

     1 def father(name):
     2     print('from father %s'%name)
     3     def son():
     4         print('from son')
     5         def grandson():
     6             print('from grandson')
     7         grandson()
     8     son()
     9 
    10 father('baba')

    六、闭包

      

     1 # 闭包:在一个作用域里放入定义变量,相当于打了一个包
     2 def father(name):
     3     def son():
     4         #name='alex'
     5         print('我爸爸是[%s]' %name)
     6         def grandson():
     7             #name='alex'
     8             print('我的爷爷是[%s]'%name)
     9         grandson()
    10     son()
    11 father('alex')

    七、无参装饰器

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

      基本框架:

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

      加上参数:

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

      加上功能:

    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

      加上返回值:

    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

      使用修饰器:

     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
    10 
    11 def cal(array):
    12     res=0
    13     for i in array:
    14         res+=i
    15     return res
    16 cal=timer(cal)
    17 print(cal(range(10)))

      语法糖@:

     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
    10 @timer
    11 def cal(array):
    12     res=0
    13     for i in array:
    14         res+=i
    15     return res
    16 #cal=timer(cal)
    17 print(cal(range(10)))

    八、装饰器应用示例

     1 user_list=[
     2     {'name':'alex','passwd':'123'},
     3     {'name':'wangjun','passwd':'123'},
     4     {'name':'liuchao','passwd':'123'},
     5     {'name':'qiaobusi','passwd':'123'}
     6 ]
     7 current_user={'username':None,'login':False}
     8 
     9 def auth_deco(func):
    10     def wrapper(*args,**kwargs):
    11         if current_user['username'] and current_user['login']:
    12             res=func(*args,**kwargs)
    13             return res
    14         username=input('用户名:').strip()
    15         passwd=input('密码:').strip()
    16         for index,user_dic in enumerate(user_list):
    17             if username==user_dic['name'] and passwd==user_dic['passwd']:
    18                 current_user['username']=username
    19                 current_user['login']=True
    20                 res=func(*args,**kwargs)
    21                 return res
    22                 break
    23             else:
    24                 print('用户名或者密码错误')
    25     return wrapper
    26 
    27 @auth_deco
    28 def index():
    29     print('欢迎来到主页面')
    30 
    31 @auth_deco
    32 def home():
    33     print('这里是你家')
    34 
    35 def shopping_car():
    36     print('查看购物车啊亲')
    37 
    38 def order():
    39     print('查看订单啊亲')
    40 
    41 index()
    42 home()
     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 import sys,threading,time
      2 
      3 
      4 class KThread(threading.Thread):
      5 
      6     """A subclass of threading.Thread, with a kill()
      7 
      8     method.
      9 
     10 
     11 
     12     Come from:
     13 
     14     Kill a thread in Python:
     15 
     16     http://mail.python.org/pipermail/python-list/2004-May/260937.html
     17 
     18     """
     19 
     20     def __init__(self, *args, **kwargs):
     21 
     22         threading.Thread.__init__(self, *args, **kwargs)
     23 
     24         self.killed = False
     25 
     26 
     27 
     28     def start(self):
     29 
     30         """Start the thread."""
     31 
     32         self.__run_backup = self.run
     33 
     34         self.run = self.__run      # Force the Thread to install our trace.
     35 
     36         threading.Thread.start(self)
     37 
     38 
     39 
     40     def __run(self):
     41 
     42         """Hacked run function, which installs the
     43 
     44         trace."""
     45 
     46         sys.settrace(self.globaltrace)
     47 
     48         self.__run_backup()
     49 
     50         self.run = self.__run_backup
     51 
     52 
     53 
     54     def globaltrace(self, frame, why, arg):
     55 
     56         if why == 'call':
     57 
     58           return self.localtrace
     59 
     60         else:
     61 
     62           return None
     63 
     64 
     65 
     66     def localtrace(self, frame, why, arg):
     67 
     68         if self.killed:
     69 
     70           if why == 'line':
     71 
     72             raise SystemExit()
     73 
     74         return self.localtrace
     75 
     76 
     77 
     78     def kill(self):
     79 
     80         self.killed = True
     81 
     82 
     83 
     84 class Timeout(Exception):
     85 
     86     """function run timeout"""
     87 
     88 
     89 
     90 def timeout(seconds):
     91 
     92     """超时装饰器,指定超时时间
     93 
     94     若被装饰的方法在指定的时间内未返回,则抛出Timeout异常"""
     95 
     96     def timeout_decorator(func):
     97 
     98         """真正的装饰器"""
     99 
    100 
    101 
    102         def _new_func(oldfunc, result, oldfunc_args, oldfunc_kwargs):
    103 
    104             result.append(oldfunc(*oldfunc_args, **oldfunc_kwargs))
    105 
    106 
    107 
    108         def _(*args, **kwargs):
    109 
    110             result = []
    111 
    112             new_kwargs = { # create new args for _new_func, because we want to get the func return val to result list
    113 
    114                 'oldfunc': func,
    115 
    116                 'result': result,
    117 
    118                 'oldfunc_args': args,
    119 
    120                 'oldfunc_kwargs': kwargs
    121 
    122             }
    123 
    124             thd = KThread(target=_new_func, args=(), kwargs=new_kwargs)
    125 
    126             thd.start()
    127 
    128             thd.join(seconds)
    129 
    130             alive = thd.isAlive()
    131 
    132             thd.kill() # kill the child thread
    133 
    134             if alive:
    135 
    136                 raise Timeout(u'function run too long, timeout %d seconds.' % seconds)
    137 
    138             else:
    139 
    140                 return result[0]
    141 
    142         _.__name__ = func.__name__
    143 
    144         _.__doc__ = func.__doc__
    145 
    146         return _
    147 
    148     return timeout_decorator
    149 
    150 
    151 @timeout(5)
    152 
    153 def method_timeout(seconds, text):
    154 
    155     print('start', seconds, text)
    156 
    157     time.sleep(seconds)
    158 
    159     print('finish', seconds, text)
    160 
    161     return seconds
    162 
    163 
    164 method_timeout(6,'asdfasdfasdfas')
  • 相关阅读:
    uninstall_edge:win10带浏览器edge卸载工具
    安装spacedesk后,Win10状态栏图标间距变宽
    jacob实现语音朗读一段文本
    汇编语言-12内中断
    告警只提示一次,未解决也不再次提示
    汇编语言-11标志寄存器
    第2章 顺序表及其顺序存储
    第1章 概论
    再见:计算机行业
    QPainter
  • 原文地址:https://www.cnblogs.com/xuanlin666/p/10845298.html
Copyright © 2020-2023  润新知