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. .net防止SQL注入的一种方式

    首先也要明白一点,什么是SQL注入 所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令.具体来说,它是利用现有应用程序,将 ...

  2. C++11 使用 std::async创建异步程序

    c++11中增加了线程,使得我们可以非常方便的创建线程,它的基本用法是这样的: void f(int n); std::thread t(f, n + 1); t.join(); 但是线程毕竟是属于比 ...

  3. HDU4704(SummerTrainingDay04-A 欧拉降幂公式)

    Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submi ...

  4. Hadoop Mapreduce 参数 (一)

    参考 hadoop权威指南 第六章,6.4节 背景 hadoop,mapreduce就如MVC,spring一样现在已经是烂大街了,虽然用过,但是说看过源码么,没有,调过参数么?调过,调到刚好能跑起来 ...

  5. BZOJ3165: [Heoi2013]Segment(李超线段树)

    题意 题目链接 Sol 李超线段树板子题.具体原理就不讲了. 一开始自己yy着写差点写自闭都快把叉积搬出来了... 后来看了下litble的写法才发现原来可以写的这么清晰简洁Orz #include& ...

  6. 【代码笔记】iOS-JQIndicatorViewDemo

    一,效果图. 二,工程图. 三,代码. #import "ViewController.h" #import "JQIndicatorView.h" @inte ...

  7. Android系统执行Java jar程序 -- dalvik运行dex Java工程

    本文仅针对纯java工程执行进行诠释,一般在PC平台作为jar包形式存在,在Android平台则以dex包形式存在. Java属于高级程序语言,Java程序需要运行在特定的虚拟机中,虚拟机将Java字 ...

  8. 【Redis】Redis学习(一) Redis初步入门

    一.Redis基础知识 1.1 Redis简介 Redis是一个开源(BSD许可),内存存储的数据结构服务器,可用作数据库,高速缓存和消息队列代理.它支持字符串.哈希表.列表.集合.有序集合,位图,h ...

  9. PHP多进程编程之僵尸进程问题

    上一篇说到了使用pcntl_fork函数可以让PHP实现多进程并发或者异步处理的效果.那么问题是我们产生的进程需要去控制,而不能置之不理.最基本的方式就是fork进程和杀死进程. 通过利用pcntl_ ...

  10. SQL Server下ADO.NET 怎么获取数据库SQL语句INSERT,UPDATE,DELETE了多少行数据

    ADO.NET 在发送SQL语句到SQL Server数据库后,怎么知道真正INSERT,UPDATE,DELETE了多少行数据呢? 使用SQL Server内置的全局变量@@ROWCOUNT即可,@ ...