装饰器的应用场景
- 附加功能
- 数据的清理或添加:
- 函数参数类型验证 @require_ints 类似请求前拦截
- 数据格式转换 将函数返回字典改为 JSON/YAML 类似响应后篡改
- 为函数提供额外的数据 mock.patch
- 函数注册
- 在任务中心注册一个任务
- 注册一个带信号处理器的函数
函数注册表
简单注册表
funcs = [] def register(func): funcs.append(func) return func @register def a(): return 3 @register def b(): return 5 # 访问结果 result = [func() for func in funcs]
注册表隔离(使用类的不同实例)
class Registry(object): def __init__(self): self._funcs = [] def register(self, func): self._funcs.append(func) def run_all(self): return [func() for func in self._funcs] r1 = Registry() r2 = Registry() @r1.register def a(): return 3 @r2.register def b(): return 5 @r1.register @r2.register
执行时封装代码
类型检查
from functools import wraps def require_ints(func): @wraps(func) # 将func的信息复制给inner def inner(*args, **kwargs): for arg list(args) + list(kwargs.values()): if not isinstance(arg, int: raise TypeError("{} 只接受int类型参数".format(func.__name__) return func(*args, **kwargs) return inner
用户验证
from functools import wraps class User(object): def __init__(self, username, email): self.username = username self.email = email class AnonymousUser(object): def __init__(self): self.username = self.email = None def __nonzero__(self): # 将对象转换为bool类型时调用 return False def requires_user(func): @wraps(func) def inner(user, *args, **kwargs): # 由于第一个参数无法支持self, 该装饰器不支持装饰类 if user and isinstance(user, User): return func(use, *args, **kwargs) else: raise ValueError("非合法用户") return inner
输出格式化
import json from functools import wraps def json_output(func): # 将原本func返回的字典格式转为返回json字符串格式 @wrap(func) def inner(*args, **kwargs): return json.dumps(func(*args, **kwargs)) return inner
异常捕获
import json from functools import wraps class Error1(Exception): def __init__(self, msg): self.msg = msg def __str__(self): return self.msg def json_output(func): @wrap(func) def inner(*args, **kwargs): try: result = func(*args, **kwargs) except Error1 as ex: result = {"status": "error", "msg": str(ex)} return json.dumps(result) return inner # 使用方法 @json_ouput def error(): raise Error1("该条异常会被捕获并按JSON格式输出")
日志管理
import time import logging from functools import wraps def logged(func): @wraps(func) def inner(*args, **kwargs): # *args可以装饰函数也可以装饰类 start = time.time() result = func(*args, **kwargs) exec_time = time.time() - start logger = logging.getLoger("func.logged") logger.warning("{} 调用时间:{:.2} 执行时间:{:.2}s 结果:{}".format(func.__name__, start, exec_time, result)
带参数的装饰器
带参数的装饰器相当于一个返回装饰器的函数,@deco(a=1)在调用@之前会首先执行deco(a=1)得到一个实际的装饰器, 带参数的装饰器deco(a=1)模块导入时立即执行
装饰类
为类增加可排序功能(而不通过继承子类扩充父类方法,比如多个类需要增加此功能时)
import time from functools import wraps def sortable_by_created(cls): original_init = cls.__init__ @wrap(original_init) def new_init(self, *args, **kwargs): original_init(*args, **kwargs) self._created = time.time() cls.__init__ = new_init cls.__lt__ = lambda self, other: self._created < other._created cls.__gt__ = lambda self, other: self._created > other._created return cls
也可定义一个SortableByCreated()类, 子类使用多重继承其父类和SortableByCreated
类型转换
函数被装饰后有可能变为一个类的实例,此时为了兼容函数调用,应为所返回的类提供__call__方法
class Task(object): def __call__(self, *args, **kwargs): return self.run(*args, **kwargs) def run(self, *args, **kwargs): raise NotImplementedError("子类未实现该接口") def task(func): class SubTask(Task): def run(self, *args, **kwargs): func(*args, **kwargs) return SubTask()
第二章 上下文管理器
定义
包装任意代码
确保执行的一致性
语法
with语句
__enter__和__exit__方法
class ContextManager(object): def __init__(self): self.entered = False def __enter__(self): self.entered = True return self def __exit__(self, exc_type, exc_instance, traceback): self.entered = False
应用场景
资源清理
import pymysql class DBConnection(object): def __init__(self, *args, **kwargs): self.args,self.kwargs = args, kwargs def __enter__(self): self.conn = pymysql.connect(*args, **kwargs) return self.conn.cursor() def __exit__(self, exc_type, exc_instance, trackback): self.conn.close()
异常处理(避免重复)
传播异常(__exit__中return False)
终止异常(__exit__中return True)
class BubleExceptions(object): def __enter__(self): return self def __exit__(self, exc_type, exc_instance, trackback): if exc_instance: print("出现异常: {}".format(exc_instance) return False # return True终止异常
处理特定的异常
class HandleValueError(object): def __enter__(self): return self def __exit__(self, exc_type, exc_instance, trackback): if not exc_type: return True if issubclass(exc_type, ValueError): print("处理ValueError: {}".format(exc_instance) return False
if issubclass...语句改为if exec_type == ValueError则不处理ValueType的子类异常
也可以根据异常的属性来判断是否传播或终止
更简单的语法
import contextlib @contextlib.contextmanager def acceptable_error_codes(*codes): try: yield except ShellException as exc_instance: if exc_instance.code not in codes: raise pass
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。
时间: 2020-04-10
python装饰器使用实例详解
这篇文章主要介绍了python装饰器使用实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 python装饰器的作用就是在不想改变原函数代码的情况下,增加新的功能.主要应用了python闭包的概念,现在用1个小例子说明 import time def foo(): time.sleep(1) def bar(): time.sleep(2) def show_time(f): def inner(): start_time = time.t
Python3.7 新特性之dataclass装饰器
Python 3.7中一个令人兴奋的新特性是 data classes . 数据类通常是一个主要包含数据的类,尽管实际上没有任何限制. 它是使用新的 @dataclass 装饰器创建的,如下所示: from dataclasses import dataclass @dataclass class DataClassCard: rank: str suit: str 此代码以及本教程中的所有其他示例仅适用于 Python 3.7 及更高版本. 注意: 当然在 Python 3.6 版本也可以使用
Python @property装饰器原理解析
这篇文章主要介绍了Python @property装饰器原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.通过@property装饰器,可以直接通过方法名来访问方法,不需要在方法名后添加一对"()"小括号. class Person: def __init__(self, name): self.__name = name @property def say(self): return self.__name xioabai
python使用装饰器作日志处理的方法
装饰器这东西我看了一会儿才明白,在函数外面套了一层函数,感觉和java里的aop功能很像:写了2个装饰器日志的例子, 第一个是不带参数的装饰器用法示例,功能相当于给函数包了层异常处理,第二个是带参数的装饰器用法示例,将日志输出到文件. ``` #coding=utf8 import traceback import logging from logging.handlers import TimedRotatingFileHandler def logger(func): def inner(*
python函数装饰器之带参数的函数和带参数的装饰器用法示例
本文实例讲述了python函数装饰器之带参数的函数和带参数的装饰器用法.分享给大家供大家参考,具体如下: 1. 函数带多个参数 # 普通的装饰器, 打印函数的运行时间 def decrator(func): def wrap(*args, **kwargs): start_time = time.time() res = func(*args, **kwargs) end_time = time.time() print('运行时间为', end_time-start_time) return
python中property和setter装饰器用法
作用:调用方法改为调用对象, 比如 : p.set_name() 改为 p.set_name 区别:前者改变get方法,后者改变set方法 效果图: 代码: class Person: def __init__(self,name): self._name = name def get_name(self): return self._name def set_name(self,name): self._name = name p = Person('小黑') print(p.get_name
python装饰器练习题及答案
这篇文章主要介绍了python装饰器练习题及答案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一:编写装饰器,为多个函数加上认证的功能(用户的账号密码) 要求登录成功一次,后续的函数都无需输入用户名和密码 FLAG=False#此时还未登录 全局变量 写这个步骤的意义在于:方便 知道已经登录成功了,就不再重复登录 def login(func):#为多个函数加上的认证功能 def inner(*args,**kwargs):#加上装饰器 gl
python装饰器实例大详解
一.作用域 在python中,作用域分为两种:全局作用域和局部作用域. 全局作用域是定义在文件级别的变量,函数名.而局部作用域,则是定义函数内部. 关于作用域,我们要理解两点: a.在全局不能访问到局部定义的变量 b.在局部能够访问到全局定义的变量,但是不能修改全局定义的变量(当然有方法可以修改) 下面我们来看看下面实例: x = 1 def funx(): x = 10 print(x) # 打印出10 funx() print(x) # 打印出1 如果局部没有定义变量x,那么函数内部会从内往
Python 装饰器深入理解
讲 Python 装饰器前,我想先举个例子,虽有点污,但跟装饰器这个话题很贴切. 每个人都有的内裤主要功能是用来遮羞,但是到了冬天它没法为我们防风御寒,咋办?我们想到的一个办法就是把内裤改造一下,让它变得更厚更长,这样一来,它不仅有遮羞功能,还能提供保暖,不过有个问题,这个内裤被我们改造成了长裤后,虽然还有遮羞功能,但本质上它不再是一条真正的内裤了.于是聪明的人们发明长裤,在不影响内裤的前提下,直接把长裤套在了内裤外面,这样内裤还是内裤,有了长裤后宝宝再也不冷了.装饰器就像我们这里说的长裤,在不
使用Python装饰器在Django框架下去除冗余代码的教程
Python装饰器是一个消除冗余的强大工具.随着将功能模块化为大小合适的方法,即使是最复杂的工作流,装饰器也能使它变成简洁的功能. 例如让我们看看Django web框架,该框架处理请求的方法接收一个方法对象,返回一个响应对象: def handle_request(request): return HttpResponse("Hello, World") 我最近遇到一个案例,需要编写几个满足下述条件的api方法: 返回json响应 如果是GET请求,那么返回错误码 做为一个注册api
深入理解Python装饰器
装饰器简介: 装饰器(decorator)是一种高级Python语法.装饰器可以对一个函数.方法或者类进行加工.在Python中,我们有多种方法对函数和类进行加工,比如在Python闭包中,我们见到函数对象作为某一个函数的返回结果.相对于其它方式,装饰器语法简单,代码可读性高.因此,装饰器在Python项目中有广泛的应用. 装饰器最早在Python 2.5中出现,它最初被用于加工函数和方法这样的可调用对象(callable object,这样的对象定义有__call__方法).在Python 2
python装饰器初探(推荐)
一.含有一个装饰器 #encoding: utf-8 ############含有一个装饰器######### def outer(func): def inner(*args, **kwargs):#要装饰f1(),这里用这俩形式参数,可以接受任意个参数,不管f1定义几个参数 print "1" r = func(*args, **kwargs)#这里要用func,不要用f1 print "2" return r return inner @outer #这里ou
深入浅出分析Python装饰器用法
本文实例讲述了Python装饰器用法.分享给大家供大家参考,具体如下: 用类作为装饰器 示例一 最初代码: class bol(object): def __init__(self, func): self.func = func def __call__(self): return "{}".format(self.func()) class ita(object): def __init__(self, func): self.func = f
Python装饰器基础详解
装饰器(decorator)是一种高级Python语法.装饰器可以对一个函数.方法或者类进行加工.在Python中,我们有多种方法对函数和类进行加工,比如在Python闭包中,我们见到函数对象作为某一个函数的返回结果.相对于其它方式,装饰器语法简单,代码可读性高.因此,装饰器在Python项目中有广泛的应用. 前面快速介绍了装饰器的语法,在这里,我们将深入装饰器内部工作机制,更详细更系统地介绍装饰器的内容,并学习自己编写新的装饰器的更多高级语法. 什么是装饰器 装饰是为函数和类指定管理代码的一种
python装饰器与递归算法详解
1.python装饰器 刚刚接触python的装饰器,简直懵逼了,直接不懂什么意思啊有木有,自己都忘了走了多少遍Debug,查了多少遍资料,猜有点点开始明白了.总结了一下解释得比较好的,通俗易懂的来说明一下: 小P闲来无事,随便翻看自己以前写的一些函数,忽然对一个最最最基础的函数起了兴趣: def sum1(): sum = 1 + 2 print(sum) sum1() 此时小P想看看这个函数执行用了多长时间,所以写了几句代码插进去了: import time def sum1(): star
Python装饰器实现几类验证功能做法实例
最近新需求来了,要给系统增加几个资源权限.尽量减少代码的改动和程序的复杂程度.所以还是使用装饰器比较科学 之前用了一些登录验证的现成装饰器模块.然后仿写一些用户管理部分的权限装饰器. 比如下面这种 def permission_required(permission): def decorator(f): @wraps(f) def decorated_function(*args, **kwargs): if not current_user.can(permission): abort(40
Python装饰器入门学习教程(九步学习)
装饰器(decorator)是一种高级Python语法.装饰器可以对一个函数.方法或者类进行加工.在Python中,我们有多种方法对函数和类进行加工,比如在Python闭包中,我们见到函数对象作为某一个函数的返回结果.相对于其它方式,装饰器语法简单,代码可读性高.因此,装饰器在Python项目中有广泛的应用. 这是在Python学习小组上介绍的内容,现学现卖.多练习是好的学习方式. 第一步:最简单的函数,准备附加额外功能 # -*- coding:gbk -*- '''示例1: 最简单的函数,表