Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.
动态地给一个对象增加一些额外的职责,就拓展对象功能来说,装饰模式比生成子类的方式更为灵活。
在Python中一切都是对象:一个实例、一个函数甚至类本身,可以将一个函数作为参数传给另一个函数,也可以将一个类作为参数传给一个函数。
def func(num):
'''定义内部函数并返回'''
def firstInnerFunc():
return 'This is the first inner function.'
def secondInnerFunc():
return 'This is the second inner function.'
if num == 1:
return firstInnerFunc
else:
return secondInnerFunc
print(func(1))
print(func(2))
print(func(1)())
print(func(2)())
上面的代码等同于:
firstFunc = func(1)
secondFunc = func(2)
print(firstFunc)
print(secondFunc)
print(firstFunc())
print(secondFunc())
输出:
.firstInnerFunc at 0x000002CF4EC51630>
.secondInnerFunc at 0x000002CF4EC516C0>
This is the first inner function.
This is the second inner function.
'''
@author: zyh
@file: demo_decorate_func.py
装饰器修饰函数的例子。
'''
import logging
logging.basicConfig(level=logging.INFO)
def loggingDecorator(func):
'''记录日志的装饰器'''
def wrapperLogging(*args, **kwargs):
logging.info('开始执行 %s() ...'%func.__name__)
func(*args, **kwargs)
logging.info('%s() 执行完成!'%func.__name__)
return wrapperLogging
@loggingDecorator
def showMin(a,b):
print('%d, %d 中的最小值是: %d' % (a, b, min(a,b)))
# decoratedShowMin = loggingDecorator(showMin)
# decoratedShowMin(2,3)
showMin(2,3)
以下两段代码等价:
@loggingDecorator
def showMin(a,b):
print('%d, %d 中的最小值是: %d' % (a, b, min(a,b)))
showMin(2,3)
def showMin(a,b):
print('%d, %d 中的最小值是: %d' % (a, b, min(a,b)))
decoratedShowMin = loggingDecorator(showMin)
decoratedShowMin(2,3)
输出:
INFO:root:开始执行 showMin() ...
2, 3 中的最小值是: 2
INFO:root:showMin() 执行完成!
装饰器可以是一个函数,也可以是一个类(必须要实现__call__方法,使其是callable的)。装饰器不仅可以修饰函数,也可以修饰类。
'''
@author: zyh
@file: demo_decorate_class.py
@time: 2023/5/9 15:47
装饰器修饰类的例子。
'''
class ClassDecorator:
'''类装饰器,记录一个类被实例化的次数'''
def __init__(self, func):
self._numOfCall = 0
self._func = func
def __call__(self, *args, **kwargs):
self._numOfCall += 1
obj = self._func(*args, **kwargs)
print('创建%s 的第%d 个实例: %s'%(self._func.__name__, self._numOfCall, id(obj)))
return obj
@ClassDecorator
class MyClass:
def __init__(self, name):
self._name = name
def getName(self):
return self._name
tony = MyClass('Tony')
billy = MyClass('Billy')
print(id(tony))
print(id(billy))
输出:
创建MyClass 的第1 个实例: 2963514621424
创建MyClass 的第2 个实例: 2963514621328
2963514621424
2963514621328
装饰模式的优点:
装饰模式相当于继承的一个替代模式。
缺点:
相比继承更容易出错,排错也更加困难。
Python装饰器与装饰模式的设计思想相似,其目标均为更好的拓展性。
区别点 |
|
|
---|---|---|
设计思想 | 函数式编程思想,即面向过程的思想 | 面向对象 |
修饰的对象 | 函数、类 | 某个类中的指定方法 |
影响范围 | 修饰一个函数时,对这个函数的所有调用都起效;修饰一个类时,对这个类的所有实例都起效 | 仅对修饰的这一个对象起效 |