博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python学习---装饰器
阅读量:6937 次
发布时间:2019-06-27

本文共 7600 字,大约阅读时间需要 25 分钟。

什么是装饰器

器即函数

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

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

装饰器需要遵循的原则

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

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

实现装饰器知识储备

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

高阶函数

高阶函数定义:

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

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

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

def foo():    print('我的函数名作为参数传给高阶函数')def gao_jie1(func):    print('我就是高阶函数1,我接收的参数名是%s' %func)    func()def gao_jie2(func):    print('我就是高阶函数2,我的返回值是%s' %func)    return funcgao_jie1(foo)gao_jie2(foo)
高阶函数示范
#高阶函数应用1:把函数当做参数传给高阶函数import timedef 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 timedef 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增加任何新功能
函数返回值是函数名

高阶函数总结

1.函数接收的参数是一个函数名
  作用:在不修改函数源代码的前提下,为函数添加新功能,
  不足:会改变函数的调用方式
2.函数的返回值是一个函数名
  作用:不修改函数的调用方式
  不足:不能添加新功能

函数嵌套

def father(name):    print('from father %s' %name)    def son():        print('from son')        def grandson():            print('from grandson')        grandson()    son()father('康明')

 闭包

'''闭包:在一个作用域里放入定义变量,相当于打了一个包'''def father(name):    def son():        # name='alex'        print('我爸爸是 [%s]' %name)        def grandson():            # name='wupeiqi'            print('我爷爷是 [%s]' %name)        grandson()    son()father('康明')

无参装饰器

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

基本框架

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

加上参数

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

加上功能

import timedef timer(func):    def wrapper(*args,**kwargs):        start_time=time.time()        func(*args,**kwargs)        stop_time=time.time()        print('函数[%s],运行时间是[%s]' %(func,stop_time-start_time))    return wrapper

加上返回值

import timedef timer(func):    def wrapper(*args,**kwargs):        start_time=time.time()        res=func(*args,**kwargs)        stop_time=time.time()        print('函数[%s],运行时间是[%s]' %(func,stop_time-start_time))        return res    return wrapper

使用装饰器

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

语法糖@

@timer  #@timer就等同于cal=timer(cal)def cal(array):    res=0    for i in array:        res+=i    return rescal(range(10))

装饰器应用示例

user_list=[    {
'name':'alex','passwd':'123'}, {
'name':'linhaifeng','passwd':'123'}, {
'name':'wupeiqi','passwd':'123'}, {
'name':'yuanhao','passwd':'123'},]current_user={
'username':None,'login':False}def auth_deco(func): def wrapper(*args,**kwargs): if current_user['username'] and current_user['login']: res=func(*args,**kwargs) return res username=input('用户名: ').strip() passwd=input('密码: ').strip() for index,user_dic in enumerate(user_list): if username == user_dic['name'] and passwd == user_dic['passwd']: current_user['username']=username current_user['login']=True res=func(*args,**kwargs) return res break else: print('用户名或者密码错误,重新登录') return wrapper@auth_decodef index(): print('欢迎来到主页面')@auth_decodef home(): print('这里是你家')def shopping_car(): print('查看购物车啊亲')def order(): print('查看订单啊亲')print(user_list)# index()print(user_list)home()
无参装饰器
user_list=[    {
'name':'alex','passwd':'123'}, {
'name':'linhaifeng','passwd':'123'}, {
'name':'wupeiqi','passwd':'123'}, {
'name':'yuanhao','passwd':'123'},]current_user={
'username':None,'login':False}def auth(auth_type='file'): def auth_deco(func): def wrapper(*args,**kwargs): if auth_type == 'file': if current_user['username'] and current_user['login']: res=func(*args,**kwargs) return res username=input('用户名: ').strip() passwd=input('密码: ').strip() for index,user_dic in enumerate(user_list): if username == user_dic['name'] and passwd == user_dic['passwd']: current_user['username']=username current_user['login']=True res=func(*args,**kwargs) return res break else: print('用户名或者密码错误,重新登录') elif auth_type == 'ldap': print('巴拉巴拉小魔仙') res=func(*args,**kwargs) return res return wrapper return auth_deco#auth(auth_type='file')就是在运行一个函数,然后返回auth_deco,所以@auth(auth_type='file')#就相当于@auth_deco,只不过现在,我们的auth_deco作为一个闭包的应用,外层的包auth给它留了一个auth_type='file'参数@auth(auth_type='ldap')def index(): print('欢迎来到主页面')@auth(auth_type='ldap')def home(): print('这里是你家')def shopping_car(): print('查看购物车啊亲')def order(): print('查看订单啊亲')# print(user_list)index()# print(user_list)home()
带参装饰器

超时装饰器

import sys,threading,timeclass KThread(threading.Thread):    """A subclass of threading.Thread, with a kill()    method.    Come from:    Kill a thread in Python:    http://mail.python.org/pipermail/python-list/2004-May/260937.html    """    def __init__(self, *args, **kwargs):        threading.Thread.__init__(self, *args, **kwargs)        self.killed = False    def start(self):        """Start the thread."""        self.__run_backup = self.run        self.run = self.__run      # Force the Thread to install our trace.        threading.Thread.start(self)    def __run(self):        """Hacked run function, which installs the        trace."""        sys.settrace(self.globaltrace)        self.__run_backup()        self.run = self.__run_backup    def globaltrace(self, frame, why, arg):        if why == 'call':          return self.localtrace        else:          return None    def localtrace(self, frame, why, arg):        if self.killed:          if why == 'line':            raise SystemExit()        return self.localtrace    def kill(self):        self.killed = Trueclass Timeout(Exception):    """function run timeout"""def timeout(seconds):    """超时装饰器,指定超时时间    若被装饰的方法在指定的时间内未返回,则抛出Timeout异常"""    def timeout_decorator(func):        """真正的装饰器"""        def _new_func(oldfunc, result, oldfunc_args, oldfunc_kwargs):            result.append(oldfunc(*oldfunc_args, **oldfunc_kwargs))        def _(*args, **kwargs):            result = []            new_kwargs = { # create new args for _new_func, because we want to get the func return val to result list                'oldfunc': func,                'result': result,                'oldfunc_args': args,                'oldfunc_kwargs': kwargs            }            thd = KThread(target=_new_func, args=(), kwargs=new_kwargs)            thd.start()            thd.join(seconds)            alive = thd.isAlive()            thd.kill() # kill the child thread            if alive:                raise Timeout(u'function run too long, timeout %d seconds.' % seconds)            else:                return result[0]        _.__name__ = func.__name__        _.__doc__ = func.__doc__        return _    return timeout_decorator@timeout(5)def method_timeout(seconds, text):    print('start', seconds, text)    time.sleep(seconds)    print('finish', seconds, text)    return secondsmethod_timeout(6,'asdfasdfasdfas')
View Code

 

转载于:https://www.cnblogs.com/kangming-/p/10010072.html

你可能感兴趣的文章