装饰器和装饰模式

先给出两者的定义:

- 装饰器:装饰器是一个非常著名的设计模式,常常被用于有切面需求的场景。较为经典的有插入日志、性能測试、事务处理等。

装饰器是解决这类问题的绝佳设计。有了装饰器,我们就能够抽离出大量函数中与函数功能本身无关的雷同代码并继续重用。概括的讲。装饰器的作用就是为已经存在的对象加入额外的功能。

- 装饰模式:在不必改变原类文件和使用继承的情况下。动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。

装饰器是python的高级函数应用的一个技巧,能够在不修改对象的前提下增强对象的功能。

这个对象能够是函数,类方法和类属型。看到“装饰”和它的功能,对于设计模式比較熟悉的同学应该会想到装饰模式。假设你如今没有想到装饰器或者对于装饰器没有一个清晰的概念认识,那么就跟我一起来复习一下装饰模式。深入理解装饰模式对于装饰器的理解会非常有帮助。

装饰模式演示样例

这里我们使用java来通过一个简单的场景展示一下装饰模式。

情景:程序员没日没夜的工作能够赚钱,把钱攒起来之后就能够买房买车,迎娶白富美。走上幸福生活。。。

这里我们定义一个能够存钱的接口:CanSaveMoney。程序员类Coder。

public interface CanSaveMoney {
public void save(int money);
}
class Coder implements CanSaveMoney { private int count = 0; @Override public void save(int money) {
count += money;
}
}
/××
×存钱的方法
××/
public void saveMoney(CanSaveMoney person, int money) {
person.save(money)
}

情景续:过了一段时间,程序员追到了女神,须要和女神培养感情。

但是我们之前不过留了一个存钱的功能没有取钱的功能,没有问题,程序员都是聪明的,我们存一个负的钱数不就是取钱了麻。

就这样程序员顺利的跟女神培养好了感情。

到了女神管理程序员的收入的时候了,女神识破了程序员的小把戏。如何修复这个漏洞呢?女神是霸道的,女神觉得程序员的一切都是她的,程序员上缴工资卡。一切都经过女神的手。

class Godness implements CanSaveMoney {

  private Coder coder;

  public Godness(Coder coder) {
this.coder = coder;
} @Override public void save(int money) {
if (money <= 0) {
throw new RuntimeException("滚犊子");
} else {
coder.save(money);
}
}
}

上面就是使用了装饰模式。在不修改原有类的情况下增强类的某一功能。

python 装饰器

python中装饰器是对装饰模式的一个更宽泛的应用,不只能够应用于类,也能应用于函数。类方法和类属性。灵活利用装饰器能够大大提高你的python开发效率。

简单的装饰器演示样例

以下是一些简单的装饰器演示样例, 展示了你能够在函数调用之前或者之后做一些处理。

import functools

# do something before call
def log(fun):
@functools.wraps(fun)
def wrapper(*args, **kwargs):
print('begin %s()' % fun.__name__)
return fun(*args, **kwargs) return wrapper # do something before and after call
def log2(fun):
@functools.wraps(fun)
def wrapper(*args, **kwargs):
print('begin call %s()' % fun.__name__)
f = fun(*args, **kwargs)
print('end call')
return f return wrapper # decorator with param
def log_tag(tag):
def log(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print('%s %s()' % (tag, func.__name__))
return func(*args, **kwargs) return wrapper return log #装饰器类,适用于须要保存一些多次调用的信息。如函数调用的次数
class LogClass(object):
def __init__(self, f):
self.f = f
self.count = 0
# 复制原函数的属性
for n in set(dir(f)) - set(dir(self)):
setattr(self, n, getattr(f, n)) def __call__(self, *args):
self.count += 1
print('called times: %s' % self.count)
return self.f(*args) def __repr__(self):
return self.f @log_tag("execute")
def print_num(n=0):
print('num is %s' % n) if __name__ == '__main__':
for n in range(1, 4):
print_num(n)
print('%s' % print_num.__name__)
关于@functools.wraps()

@functools.wraps()是functools模块中一个非常实用的装饰器,它的作用是把原函数的属性拷贝到装饰过的函数中。函数也是对象,所以函数的属性这也概念不难理解,比如你能够使用pirnt('%s' % print_num.__name__)来打印出函数的名称属性。这里重点解释装饰过的函数并不是原函数。

上面的代码片断最后我们打印出了函数的名称属性。假设我们把装饰器中的@functools.wraps()这一行凝视掉之后。再运行打印,打印出的结果不会再是print_numm了。而是wrapper。弄清晰原因你就理解了@functools.wraps()的作用。

为什么装饰过的函数的print_num.__name__改变了?

上面我们使用@log的形式来使用装饰器装饰函数。这在python里面叫装饰器语法。不使用装饰器语法的的形式是这种

print_num = log(print_num)
print_num(n)

这样我们就理解了为什么装饰过后的函数不再是原来的函数了。上面代码段中装饰器类初始化代码中获取设置原函数属性的作用相似于@functools.wraps()的作用。

装饰模式和python装饰器的更多相关文章

  1. python装饰器2

    装饰模式有很多经典的使用场景,例如插入日志.性能测试.事务处理等等,有了装饰器,就可以提取大量函数中与本身功能无关的类似代码,从而达到代码重用的目的.下面就一步步看看Python中的装饰器. 一个简单 ...

  2. 关于python装饰器

    关于python装饰器,不是系统的介绍,只是说一下某些问题 1 首先了解变量作用于非常重要 2 其次要了解闭包 def logger(func): def inner(*args, **kwargs) ...

  3. python装饰器通俗易懂的解释!

    1.python装饰器 刚刚接触python的装饰器,简直懵逼了,直接不懂什么意思啊有木有,自己都忘了走了多少遍Debug,查了多少遍资料,猜有点点开始明白了.总结了一下解释得比较好的,通俗易懂的来说 ...

  4. Python 装饰器学习

    Python装饰器学习(九步入门)   这是在Python学习小组上介绍的内容,现学现卖.多练习是好的学习方式. 第一步:最简单的函数,准备附加额外功能 1 2 3 4 5 6 7 8 # -*- c ...

  5. python 装饰器修改调整函数参数

    简单记录一下利用python装饰器来调整函数的方法.现在有个需求:参数line范围为1-16,要求把9-16的范围转化为1-8,即9对应1,10对应2,...,16对应8. 下面是例子: def fo ...

  6. python 装饰器学习(decorator)

    最近看到有个装饰器的例子,没看懂, #!/usr/bin/python class decorator(object): def __init__(self,f): print "initi ...

  7. Python装饰器详解

    python中的装饰器是一个用得非常多的东西,我们可以把一些特定的方法.通用的方法写成一个个装饰器,这就为调用这些方法提供一个非常大的便利,如此提高我们代码的可读性以及简洁性,以及可扩展性. 在学习p ...

  8. 关于python装饰器(Decorators)最底层理解的一句话

    一个decorator只是一个带有一个函数作为参数并返回一个替换函数的闭包. http://www.xxx.com/html/2016/pythonhexinbiancheng_0718/1044.h ...

  9. Python装饰器由浅入深

    装饰器的功能在很多语言中都有,名字也不尽相同,其实它体现的是一种设计模式,强调的是开放封闭原则,更多的用于后期功能升级而不是编写新的代码.装饰器不光能装饰函数,也能装饰其他的对象,比如类,但通常,我们 ...

随机推荐

  1. ORA-00922: 选项缺失或无效

    1.错误描写叙述 SQL> create table info_stu from select t.stu_id,t.stu_name,t.stu_age from info t; create ...

  2. JavaWeb-04(BOM&amp;DOM)

    JavaWeb-04 JavaWeb-BOM&DOM BOM 一.知识回想 * BOM 概述 * BOM 的各个对象 * window对象 innerHeight,innerWidth doc ...

  3. css中margin上下外边距重叠问题

    css的盒子模型里是这样规定两个对象之间的距离的:对象之间的间距是由两个对象的盒子模型的最终计算值得出来的,也就是说两个对象之间的间距就是两个对象的距离,但是当遇到两个对象一个有下外边距margin, ...

  4. js全局的解析与执行过程

    先看下面实例的执行结果: alert(a);//undefined alert(b);//报错 alert(f);//输出f函数字符串 alert(g);//undefined var a = 1; ...

  5. double 失真例子

    public static void main(String[] args) {  // TODO Auto-generated method stub  double ab=821.20;  dou ...

  6. NO.1 You must restart adb and Eclipse多种情形分析与解决方式

    一:错误提示 The connection to adb is down, and a severe error has occured. You must restart adb and Eclip ...

  7. Windows Server 2016 关闭Internet Explorer增强的安全配置

    Windows Server 2016 关闭Internet Explorer增强的安全配置 IE11 默认启用 Internet Explorer 增强的安全配置,浏览网页时这个提示十分频繁,是不是 ...

  8. golang sync.Mutex

    //go func 和主线程之间的关系是并行和竞争关系 package main import ( "fmt" "sync" "time" ...

  9. C# 异步延时执行

    https://blog.csdn.net/xiawu1990/article/details/78350253?utm_source=blogxgwz7 var t = Task.Run(async ...

  10. (转)Tomcat目录结构

    首先来了解一下Tomcat5.5的目录结构: /bin:存放windows或Linux平台上启动和关闭Tomcat的脚本文件 /conf:存放Tomcat服务器的各种全局配置文件,其中包括server ...