1.最简单的装饰器不带入参

def  func():

pass

def  decorate(func)

  def wrapper():

    return func()

  return wrapper

使用

@decorate

def  aa(m):

pass

2.要是带参数就简单给他就是了:

因为函数有千千万,你只管你自己的函数,别人的函数参数是什么样子,鬼知道?还好Python提供了可变参数*args和关键字参数**kwargs,有了这两个参数,装饰器就可以用于任意目标函数了。

def  decorate(func)

  def wrapper(*args,**kwargs):

    return func((*args,**kwargs)

  return wrapper

如何优化你的装饰器#

嵌套的装饰函数不太直观,我们可以使用第三方包类改进这样的情况,让装饰器函数可读性更好。

decorator.py#

decorator.py 是一个非常简单的装饰器加强包。你可以很直观的先定义包装函数wrapper(),再使用decorate(func, wrapper)方法就可以完成一个装饰器。

Copy
from decorator import decorate

def wrapper(func, *args, **kwargs):
"""print log before a function."""
print "[DEBUG] {}: enter {}()".format(datetime.now(), func.__name__)
return func(*args, **kwargs) def logging(func):
return decorate(func, wrapper) # 用wrapper装饰func

你也可以使用它自带的@decorator装饰器来完成你的装饰器。

Copy
from decorator import decorator

@decorator
def logging(func, *args, **kwargs):
print "[DEBUG] {}: enter {}()".format(datetime.now(), func.__name__)
return func(*args, **kwargs)

decorator.py实现的装饰器能完整保留原函数的namedocargs,唯一有问题的就是inspect.getsource(func)返回的还是装饰器的源代码,你需要改成inspect.getsource(func.__wrapped__)

wrapt#

wrapt是一个功能非常完善的包,用于实现各种你想到或者你没想到的装饰器。使用wrapt实现的装饰器你不需要担心之前inspect中遇到的所有问题,因为它都帮你处理了,甚至inspect.getsource(func)也准确无误。

Copy
import wrapt

# without argument in decorator
@wrapt.decorator
def logging(wrapped, instance, args, kwargs): # instance is must
print "[DEBUG]: enter {}()".format(wrapped.__name__)
return wrapped(*args, **kwargs) @logging
def say(something): pass

使用wrapt你只需要定义一个装饰器函数,但是函数签名是固定的,必须是(wrapped, instance, args, kwargs),注意第二个参数instance是必须的,就算你不用它。当装饰器装饰在不同位置时它将得到不同的值,比如装饰在类实例方法时你可以拿到这个类实例。根据instance的值你能够更加灵活的调整你的装饰器。另外,argskwargs也是固定的,注意前面没有星号。在装饰器内部调用原函数时才带星号。

如果你需要使用wrapt写一个带参数的装饰器,可以这样写。

Copy
def logging(level):
@wrapt.decorator
def wrapper(wrapped, instance, args, kwargs):
print "[{}]: enter {}()".format(level, wrapped.__name__)
return wrapped(*args, **kwargs)
return wrapper @logging(level="INFO")
def do(work): pass

关于wrapt的使用,建议查阅官方文档,在此不在赘述。

  • http://wrapt.readthedocs.io/en/latest/quick-start.html

小结#

Python的装饰器和Java的注解(Annotation)并不是同一回事,和C#中的特性(Attribute)也不一样,完全是两个概念。

装饰器的理念是对原函数、对象的加强,相当于重新封装,所以一般装饰器函数都被命名为wrapper(),意义在于包装。函数只有在被调用时才会发挥其作用。比如@logging装饰器可以在函数执行时额外输出日志,@cache装饰过的函数可以缓存计算结果等等。

而注解和特性则是对目标函数或对象添加一些属性,相当于将其分类。这些属性可以通过反射拿到,在程序运行时对不同的特性函数或对象加以干预。比如带有Setup的函数就当成准备步骤执行,或者找到所有带有TestMethod的函数依次执行等等。

至此我所了解的装饰器已经讲完,但是还有一些内容没有提到,比如装饰类的装饰器。有机会再补充。谢谢观看。

装饰器 python 你也可以叫语法糖的更多相关文章

  1. 装饰器python

    装饰器 你是一家视频网站的后端开发工程师,你们网站有以下几个版块 1 2 3 4 5 6 7 8 9 10 11 def home():     print("---首页----" ...

  2. 函数与装饰器Python学习(三)

    1.1 文件处理 1.1.1 打开文件过程 在Python中,打开文件,得到文件句柄并赋值给一个变量,默认打开模式就为r f=open(r'a.txt','w',encoding='utf-8') p ...

  3. 函数 装饰器 python

    今日内容概要 1.闭包函数 2.闭包函数的实际应用 3.装饰器简介(重点加难点) 4.简易版本装饰器 5.进阶版本装饰器 6.完整版本装饰器 7.装饰器模板(拷贝使用即可) 8.装饰器语法糖 9.装饰 ...

  4. 浅谈装饰器(Python)

    先来了解函数和执行函数在python的区别   我再重新定义一个函数,在函数前面加上@set_func 执行结果如下:   函数前面没有加@set_fun 执行结果如下:   是不是可以不修改原来的函 ...

  5. 装饰器(Python)

    装饰器(decorators)是 Python 的一个重要部分.简单地说:装饰器是修改其他函数的功能的函数,能让我们的代码更容易被扩展,更加简短.举个例子: def login(): print(&q ...

  6. Python - 编程技巧,语法糖,黑魔法,pythonic

    参考,搬运 http://python-web-guide.readthedocs.io/zh/latest/idiom/idiom.html 待定 1. Python支持链式比较 # bad a = ...

  7. 简单说明Python中的装饰器的用法

    简单说明Python中的装饰器的用法 这篇文章主要简单说明了Python中的装饰器的用法,装饰器在Python的进阶学习中非常重要,示例代码基于Python2.x,需要的朋友可以参考下   装饰器对与 ...

  8. 【转】Python之装饰器

    [转]Python之装饰器 本节内容 必要知识回顾 情景模拟 装饰器的概念及实现原理 回马枪(带参数的装饰器) 一. 必要知识回顾 在开始说装饰器之前,需要大家熟悉之前说过的相关知识点: 函数即“变量 ...

  9. python 闭包@装饰器

    1.装饰器 装饰器(Decorator)相对简单,咱们先介绍它:“装饰器的功能是将被装饰的函数当作参数传递给与装饰器对应的函数(名称相同的函数),并返回包装后的被装饰的函数”,听起来有点绕,没关系,直 ...

随机推荐

  1. ssm中逆向工程与分页的应用

    昨天对springboot中的mybatis逆向工程与分页应用进行了整理,今天对ssm项目中的逆向工程与分页进行整理. 项目运行环境:eclipse+jdk1.8+maven+tomcat 一.搭建s ...

  2. Ubuntu下自定义调整CPU工作频率(用于省电或提高性能都好用)

    昨天高铁上拿T480切win10系统看电影,为了节电给细调了个省电策略(设置CPU性能30%),不知是不是因为这个原因,今天切回Ubuntu1604工作导致CPU工作频率非常低. 查阅了一下相关方法, ...

  3. Ubuntu14.16.18更新源

    一.源概述 源,可以认为是软件库,使用apt-get install安装的时候,会在源保存的库中进行搜索,因此源(默认源在欧洲)会影响下载速度和资源数量 二.更新源 1.步骤 编辑/etc/apt/s ...

  4. Mybatis中使用循环遍历

    Mybatis中传参数的方法 1.使用注解绑定,mapper.xml 对应方法 不需要指定 parameterType,(推荐使用注解绑定方式) 方法接口: List<CalculateIdea ...

  5. Map对象以及for of的使用方法

  6. 从零开始学习html(十五)css样式设置小技巧——下

    六.垂直居中-父元素高度确定的单行文本 <!DOCTYPE HTML> <html> <head> <meta charset="utf-8&quo ...

  7. OSGI企业应用开发(九)整合Spring和Mybatis框架(二)

    上篇文章中,我们完成了在OSGI应用中整合Spring和Mybatis框架的准备工作,本节我们继续Spring和Mybatis框架的整合. 一.解决OSGI整合Spring中的Placeholder问 ...

  8. 百度Ocr文字识别

    简述 最近开发一个项目需要用到Ocr文字识别技术来识别手写文字,在评估过程中体验了百度的文字识别和腾讯的文字识别.查找官方开发文档,发现它们都有印刷体和手写体两种符合项目需求的识别模式,但是腾讯的手写 ...

  9. 微信为啥不能直接下载.apk安装包

    今天遇到一个很蛋疼问题,我们的微信公众号上想放一个下载自己公司app的点击按钮,如果是苹果手机点击这个按钮就直接跳转到苹果的appstore,如果是android手机的话,就直接跳我们的服务器下载ap ...

  10. Django 处理modelform错误信息

    cp:https://blog.csdn.net/qq_34964399/article/details/79781071