开放封闭原则的定义
开放封闭原则(OCP, Open CLosed Principle)是所有面向对象原则的核心。”需求总是变化的”,所以诞生出了这种原则,它主要体现在两方面
- 对扩展开放,意味着有心得需求的时候,可以对现有的代码进行拓展,以适应新的情况
- 对修改封闭,意味着类一但设计完成,就可以独立完成其工作,就不要对类进行任何的修改
装饰器使用的场景
多用于插入日志,性能测试,事务处理,缓存,权限校验等场景。接下来我们以性能测试为例子
#这是装饰器的常用写法(被包装的函数拥有参数和返回值的)
def wrapper(func):
#因为装饰器是谁都可以使用的,我们无法确定任何函数的参数个数,所以我们用不定参
def inner(*args, **kwargs):
ret = func(*args, **kwargs)
return ret
return inner
@wrapper #相当于say = wrapper(say)
def say(something):
return something
say('hello')
假设我们有两个函数f1和f2,他们都实现同一个功能。我们要比较两者的性能谁更优,我们当然可以直接把测试函数test写好,然后让两者内部调用,输出结果。可是这不符合封闭开放原则,下面是装饰器的写法
import time
def wrapper(func):
def test():
print(func.__name__)
start_time = time.time()
func()
end_time = time.time()
print(end_time - start_time)
return test
@wrapper #相当与f1 = wrapper(f1)
def f1():
pass
@wrapper #相当于f2 = wrapper(f2)
def f2():
pass
f1()
f2()
高级一点的装饰器
1. 带有参数的装饰器
def loggging(level):
def wrapper(func):
def inner(*args, **kwargs):
print('{level}: enter {func} function'.format(level=level,func=func.__name__))
ret = func(*args, **kwargs):
return ret
return inner
return wrapper
#相当于是先执行了logging()函数,返回了一个wrapper
@logging('INFO')
def say(something):
return something
2. 类装饰器
在说类装饰器之前,我们需要了解一个python的内置方法call(将实例变成可调用对象)
class Person():
def __call__(self):
print("hello world")
p = Person()
p() #hello world
类中装饰器的常用写法(其实就是用init来传递func,用call来调用)
class logging(object):
def __init__(self, func):
self.func = func
def __call__(self, *args, *kwargs):
print(self.func.__name__)
retrun self.func(*args, **kwargs)
@logging
def say(something):
return something
总结
若是想使函数的功能得到拓展而又不修改函数的本身,那么就使用装饰器吧