zoukankan      html  css  js  c++  java
  • Python成长之路【第七篇】:Python基础之装饰器

    一、什么是装饰器

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

    器:器既函数

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

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

    1、不能修改装饰器的源代码(开放封闭原则)

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

    三、实现装饰器的知识储备

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

    四、高阶函数 

    高阶函数的定义:

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

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

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

     1 def foo():
     2     print('我的函数名作为参数传给高阶函数')
     3 def gao_jie1(func):
     4     print('我就是高阶函数1,我接收的参数名是%s' %func)
     5     func()
     6 
     7 def gao_jie2(func):
     8     print('我就是高阶函数2,我的返回值是%s' %func)
     9     return func
    10 
    11 gao_jie1(foo)
    12 gao_jie2(foo)
    高阶函数示范
     1 #高阶函数应用1:把函数名当做参数传给高阶函数
     2 import time
     3 def foo():
     4     print('from the foo')
     5 
     6 def timmer(func):
     7     start_time=time.time()
     8     func()
     9     stop_time=time.time()
    10     print('函数%s 运行时间是%s' %(func,stop_time-start_time))
    11 timmer(foo)
    12 #总结:我们确实为函数foo增加了foo运行时间的功能,但是foo原来的执行方式是foo(),现在我们需要调用高阶函数timmer(foo),改变了函数的调用方式
    把函数名当做参数传给高阶函数
     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、函数的返回值是一个函数名

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

      不足:不能添加新功能

     五、函数嵌套

    def foo(name):
        print("from foo %s" %name)
        def ret():
            print("from ret")
            def bar():
                print("from bar")
            bar()
        ret()
        
    foo("Albert")
    

    六、闭包

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

    def foo(name):
        def ret():
            print("123%s"%name)
            def bar():
                print("456%s"%name)
            bar()
        ret()
    
    foo("Albert")
    

    七、没有参数的装饰器

    没有参数的装饰器 = 高阶函数 + 函数嵌套

    基本框架

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

    加上参数

    def timer(func):
        def wrapper(*args, **kwargs):
            func(*args, **kwargs)
        return wrapper
    

    加上功能

    import time
    
    def timer(func):
        def wrapper(*args, **kwargs):
            s_time = time.time()
            func(*args, **kwargs)
            e_time = time.time()
            print("函数【%s】,运行的时间是%s"%(func, e_time - s_time))
        return wrapper
    

      

    加上返回值

    import time
    
    def timer(func):
        def wrapper(*args, **kwargs):
            s_time = time.time()
            res = func(*args, **kwargs)
            e_time = time.time()
            print("函数【%s】,运行的时间是%s"%(func, e_time - s_time))
            return res
        return wrapper
    

      

    使用装饰器

    def cal(array):
        res = 0
        for i in array:
            res += i
        return res
    
    cal = timer(cal)
    a = cal(range(10))
    print(a)
    

    语法糖@

    @timer # @timer == cal = timer(cal)
    def cal(array):
        res = 0
        for i in array:
            res += i
        return res
    
    
    a = cal(range(10))
    print(a)
    

    八、装饰器应用示例

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

     九、超时装饰器

      1 import sys,threading,time
      2 
      3 class KThread(threading.Thread):
      4 
      5     """A subclass of threading.Thread, with a kill()
      6 
      7     method.
      8 
      9 
     10 
     11     Come from:
     12 
     13     Kill a thread in Python:
     14 
     15     http://mail.python.org/pipermail/python-list/2004-May/260937.html
     16 
     17     """
     18 
     19     def __init__(self, *args, **kwargs):
     20 
     21         threading.Thread.__init__(self, *args, **kwargs)
     22 
     23         self.killed = False
     24 
     25 
     26 
     27     def start(self):
     28 
     29         """Start the thread."""
     30 
     31         self.__run_backup = self.run
     32 
     33         self.run = self.__run      # Force the Thread to install our trace.
     34 
     35         threading.Thread.start(self)
     36 
     37 
     38 
     39     def __run(self):
     40 
     41         """Hacked run function, which installs the
     42 
     43         trace."""
     44 
     45         sys.settrace(self.globaltrace)
     46 
     47         self.__run_backup()
     48 
     49         self.run = self.__run_backup
     50 
     51 
     52 
     53     def globaltrace(self, frame, why, arg):
     54 
     55         if why == 'call':
     56 
     57           return self.localtrace
     58 
     59         else:
     60 
     61           return None
     62 
     63 
     64 
     65     def localtrace(self, frame, why, arg):
     66 
     67         if self.killed:
     68 
     69           if why == 'line':
     70 
     71             raise SystemExit()
     72 
     73         return self.localtrace
     74 
     75 
     76 
     77     def kill(self):
     78 
     79         self.killed = True
     80 
     81 
     82 
     83 class Timeout(Exception):
     84 
     85     """function run timeout"""
     86 
     87 
     88 
     89 def timeout(seconds):
     90 
     91     """超时装饰器,指定超时时间
     92 
     93     若被装饰的方法在指定的时间内未返回,则抛出Timeout异常"""
     94 
     95     def timeout_decorator(func):
     96 
     97         """真正的装饰器"""
     98 
     99 
    100 
    101         def _new_func(oldfunc, result, oldfunc_args, oldfunc_kwargs):
    102 
    103             result.append(oldfunc(*oldfunc_args, **oldfunc_kwargs))
    104 
    105 
    106 
    107         def _(*args, **kwargs):
    108 
    109             result = []
    110 
    111             new_kwargs = { # create new args for _new_func, because we want to get the func return val to result list
    112 
    113                 'oldfunc': func,
    114 
    115                 'result': result,
    116 
    117                 'oldfunc_args': args,
    118 
    119                 'oldfunc_kwargs': kwargs
    120 
    121             }
    122 
    123             thd = KThread(target=_new_func, args=(), kwargs=new_kwargs)
    124 
    125             thd.start()
    126 
    127             thd.join(seconds)
    128 
    129             alive = thd.isAlive()
    130 
    131             thd.kill() # kill the child thread
    132 
    133             if alive:
    134 
    135                 raise Timeout(u'function run too long, timeout %d seconds.' % seconds)
    136 
    137             else:
    138 
    139                 return result[0]
    140 
    141         _.__name__ = func.__name__
    142 
    143         _.__doc__ = func.__doc__
    144 
    145         return _
    146 
    147     return timeout_decorator
    148 
    149 
    150 @timeout(5)
    151 
    152 def method_timeout(seconds, text):
    153 
    154     print('start', seconds, text)
    155 
    156     time.sleep(seconds)
    157 
    158     print('finish', seconds, text)
    159 
    160     return seconds
    161 
    162 
    163 method_timeout(6,'asdfasdfasdfas')
    查看代码
  • 相关阅读:
    区间更新+单点查询
    第15题 三个数的和为确定值
    第12题 数字转为罗马数字
    第11题 容器装水问题
    第22章 软件安装:源码与Tarball
    第18章 认识系统服务(daemons)
    第10题 正则表达式匹配(动态规划)
    动态规划
    第6题 ZigZag转换
    第17章 程序管理与SELinux初探
  • 原文地址:https://www.cnblogs.com/albert0924/p/8760575.html
Copyright © 2011-2022 走看看