阅读量

原创教程,严禁转载。引用本文,请署名 Python中文网, http://www.zglg.work


十三、Python 装饰器

装饰器,几乎各大Python框架中都能看到它的身影,足以表明它的价值!它有动态改变函数或类功能的魔力!

1 什么是装饰器

对于受到封装的原函数比如f来说,装饰器能够在f函数执行前或者执行后分别运行一些代码。

2 装饰器的结构

装饰器也是一个函数,它装饰原函数f或类cls后,再返回一个函数g,因此装饰器的结构如下:

装饰一个函数:

def decorator(f):
  # 定义要返回的函数
  def g():
    print('函数f执行前的动作')
    f()
    print('函数f执行后的动作')
  return g

装饰一个类:

def decorator(cls):
  # 定义要返回的函数
  def g():
    print('类cls执行前的动作')
    f()
    print('类cls执行后的动作')
  return g

使用装饰器很简单,@+自定义装饰器 装饰要想装饰的函数。

3 为什么要这样

要想理解装饰器为什么要有这种结构,要首先想明白装饰器的目标是什么。

它的价值在于为原函数f增加一些行为,前提必须不能破坏函数f,所以肯定不能改变f的内部结构,所以只能在调用f前后定义一些行为。

同时,装饰器函数decorator返回值又是什么? 你可以思考下,返回一个函数是再好不过的了,它包装了原函数f.

4 装饰一个函数

printStar函数接收一个函数f,返回值也是一个函数,所以满足装饰器的结构要求,所以printStar是一个装饰器。

def printStar(f):
    def g():
        print('*'*20)
        f()
        print('*'*20)
    return g

printStar装饰器实现f函数执行前、后各打印20个*字符。

使用printStar:

@printStar
def f():
    print('hello world')

调用:

if __name__ == '__main__':
   ### 改变函数功能
   f()

打印结果:

********************
hello world
********************

可以很方便的装饰要想装饰的其他函数,如下:

@printStar
def g():
    print('welcome to Python')

5 装饰一个类

除了可以装饰函数f外,还可以装饰类cls,两者原理都是一样的。

下面给出一个装饰器实现单例模式的例子,所谓单例就是类只有唯一实例,不能有第二个。

def singleton(cls):
   instance = {}

   def get_instance(*args, **kwargs):
       if cls not in instance:
           instance[cls] = cls(*args, **kwargs)
       return instance[cls]
   return get_instance

定义字典instance,键值对分别为类和实例,这样确保只cls()一次。

使用装饰器singleton修饰类:

@singleton
class CorePoint:
   pass

测试:

if __name__ == '__main__':
   ### 改变类的功能
   c1 = CorePoint()
   c2 = CorePoint()
   print(c1 is c2) # True

Python 20个专题完整目录:

Python前言

Google Python代码风格指南

Python数字

Python正则之提取正整数和大于0浮点数

Python字符串

CSV读写乱码问题

Unicode标准化

Unicode, UTF-8, ASCII

Python动态生成变量

Python字符串对齐

Python小项目1:文本句子关键词的KWIC显示

Python列表

Python流程控制

Python编程习惯专题

Python函数专题

Python面向对象编程-上篇

Python面向对象编程-下篇

Python十大数据结构使用专题

Python包和模块使用注意事项专题

Python正则使用专题

Python时间专题

Python装饰器专题

Python迭代器使用专题

Python生成器使用专题

Python 绘图入门专题

Matplotlib绘图基础专题

Matplotlib绘图进阶专题

Matplotlib绘图案例

NumPy图解入门