装饰器和装饰模式

先给出两者的定义:

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

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

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

装饰器是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. PHP实现事件机制实例分析

    PHP实现事件机制实例分析 内置了事件机制的语言不多,php也没有提供这种功能.事件(Event)说简单了就是一个Observer模式.实现起来非常easy.可是有所不同的是,事件的监听者谁都能够加, ...

  2. 作为刚開始学习的人应该怎样来学习FPGA

    FPGA作为一种高新的技术.已经逐渐普及到了各行各业.不管是消费类.通信类.电子行业都无处不在它的身影,从1985年第一颗FPGA诞生至 今,FPGA已经历了将近20多个年头,从当初的几百个门电路到如 ...

  3. Scrum中的产品需求预审

    原文作者:Mike Cohn 为了保持产品待办事项(product backlog)的整洁有序,我们须要召开product backlog refinement会议(有时也叫product backl ...

  4. uva103 - Stacking Boxes(DAG)

    题目:uva103 - Stacking Boxes(DAG) 题目大意:给出N个boxes, 而且给出这些箱子的维度.要求找一个最长的序列.可以使得以下的箱子一定可以有个维度序列大于上面的那个箱子的 ...

  5. js01----json,数组

    <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content ...

  6. mapper.xml中的常用标签

    mybatis的mapper xml文件中的常用标签 https://blog.csdn.net/qq_41426442/article/details/79663467 SQL语句标签 1.查询语句 ...

  7. c#程序打包、机器代码生成(Ngen.exe)

    深入本机影像生成器(Ngen.exe)工具使用方法详解 先介绍一点背景知识:.Net程序在运行时会实时(JIT)编译,将.Net程序文件编译成cpu认识的汇编机器码.实时编译需要消耗额外的cpu和内存 ...

  8. Mysql学习总结(13)——使用JDBC处理MySQL大数据

    一.基本概念 大数据也称之为LOB(Large Objects),LOB又分为:clob和blob,clob用于存储大文本,blob用于存储二进制数据,例如图像.声音.二进制文等. 在实际开发中,有时 ...

  9. 信号 signal sigaction补充

    目前linux中的signal()是通过sigation()函数实现的. 由signal()安装的实时信号支持排队,同样不会丢失. 先看signal 和 sigaction 的区别: 关键是 stru ...

  10. BZOJ2882

    传送门:BZOJ2882(权限题) 最小表示法的模板. 传送门:周神论文 代码上的小细节见下. #include <cstdio> #include <cstdlib> #in ...