详解python装饰器

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/strongbill/article/details/82768096

开放封闭原则的定义

开放封闭原则(OCP, Open CLosed Principle)是所有面向对象原则的核心。”需求总是变化的”,所以诞生出了这种原则,它主要体现在两方面

  1. 对扩展开放,意味着有心得需求的时候,可以对现有的代码进行拓展,以适应新的情况
  2. 对修改封闭,意味着类一但设计完成,就可以独立完成其工作,就不要对类进行任何的修改

装饰器使用的场景

多用于插入日志,性能测试,事务处理,缓存,权限校验等场景。接下来我们以性能测试为例子

#这是装饰器的常用写法(被包装的函数拥有参数和返回值的)
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

总结

若是想使函数的功能得到拓展而又不修改函数的本身,那么就使用装饰器吧

猜你喜欢

转载自blog.csdn.net/strongbill/article/details/82768096