Python装饰器

Python装饰器

  • 装饰器的功能和实现方法
    • 功能:对函数和类功能进行扩展
    • 装饰模式有不少经典的使用场景,例如插入日志、性能测试、事务处理等等,有了装饰器,就能够提取大量函数中与自己功能无关的相似代码,从而达到代码重用的目的。
    • 实现:装饰器能够是函数,也能够是一个对象,总之是能够将要装饰的函数做为参数传入并返回函数或对象再赋值给函数或类
    • 装饰器语法糖:在Python中,可使用”@”语法糖来精简装饰器的代码
    • 下面使用不一样的方式实现装饰器来讲明:
# 使用装饰器函数装饰函数
def decorator(func):
    print(func)
    #这就是将来的demo函数
    def inner():
        print('执行demo函数以前增长一些功能')
        func()
        print('执行demo函数以后增长一些功能')
    #返回内部函数做为将来的demo函数
    return inner

# 语法糖,使用decorator函数来装饰demo函数,至关于demo = decorator(demo)
@decorator
def demo():
    print('测试装饰器的函数')
    return 0

demo()
复制代码
<function demo at 0x000001D3146CE158>
执行demo函数以前增长一些功能
测试装饰器的函数
执行demo函数以后增长一些功能
复制代码
# 实现带有参数和返回值的装饰器
def decorator(func):
    print(func)
    #这就是将来的demo函数(原函数有什么形参,这里就要有什么形参)
    def inner(var):
        print('执行demo函数以前增长一些功能')
        res = func(var)
        print('执行demo函数以后增长一些功能')
        return res
    #返回内部函数做为将来的demo函数
    return inner

# 使用decorator函数来装饰demo函数
@decorator
def demo(var):
    print('测试装饰器的函数')
    return var

test = demo('测试')
print(test)
复制代码
<function demo at 0x000001D3146EE048>
执行demo函数以前增长一些功能
测试装饰器的函数
执行demo函数以后增长一些功能
测试
复制代码
# 带有参数的装饰器(给装饰器加参数,根据不一样的参数实现不一样的扩展功能)
def outer(arg):
    
    def decorator(func):
        print(func)
        #这就是将来的demo函数(原函数有什么形参,这里就要有什么形参)
        def inner1(var):
            print('执行demo函数以前增长一些功能1')
            res = func(var)
            print('执行demo函数以后增长一些功能1')
            return res
        def inner2(var):
            print('执行demo函数以前增长一些功能2')
            res = func(var)
            print('执行demo函数以后增长一些功能2')
            return res
        if arg == 1 :
            #返回内部函数做为将来的demo函数
            return inner1
        elif arg == 2 :
            return inner2
    return decorator

# 使用decorator函数来装饰demo函数,参数为1
# outer(1) 返回的是函数decorator,
# 此操做等同于 demo = outer(1)(demo) --> demo = decorator(demo)[arg = 1]
@outer(1)
def demo(var):
    print('测试装饰器的函数')
    return var

test = demo('测试')
print(test)

print('\n###############################################\n')
# 使用decorator函数来装饰demo函数,参数为2
# outer(2) 返回的是函数decorator,
# 此操做等同于 demo = outer(2)(demo) --> demo = decorator(demo)[arg = 2]
@outer(2)
def demo(var):
    print('测试装饰器的函数')
    return var

test = demo('测试')
print(test)
复制代码
<function demo at 0x000001D3146CE840>
执行demo函数以前增长一些功能1
测试装饰器的函数
执行demo函数以后增长一些功能1
测试

###############################################

<function demo at 0x000001D314702B70>
执行demo函数以前增长一些功能2
测试装饰器的函数
执行demo函数以后增长一些功能2
测试
复制代码
# 将类做为装饰器使用
class decorator:
    # 初始化魔术方法
    def __init__(self,arg):
        self.arg = arg
    
    # 当对象被当作函数调用时触发
    def __call__(self,func):
        self.func = func
        return self.inner
    # 装饰函数
    def inner(self,var):
        print('执行demo函数以前增长一些功能2')
        res = self.func(var)
        print('执行demo函数以后增长一些功能2')
        return res
        
# 实例化类decorator,将实例化后的对象做为函数使用
# 等同于demo = decorator(1)(demo) --> demo = decorator(1).__call__(demo)
# 必需要存在的函数,__init__()用于接收@decorator(1) 中的1,
# __call__()用于实现将对象当作函数调用的功能,须要接收demo函数
# __inner__()函数,用来装饰demo函数的装饰函数
@decorator(1)
def demo(var):
    print(var)
    return var
    
res = demo('123')
print(res) 
复制代码
执行demo函数以前增长一些功能2
123
执行demo函数以后增长一些功能2
123
复制代码
# 使用装饰器实现类的单例模式,为类添加装饰器
objs = {}
# 须要接收的参数是类,能够对多个类实现单例模式
def decorator(cls):
    #装饰函数,返回cls类型的对象
    def inner():
        obj = None
        if cls in objs:
            return objs[cls]
        else :
            obj = object.__new__(cls)
            objs[cls] = obj
        return obj
    return inner

# 只要在类上加上装饰器就能够实现单例模式
@decorator
class demo1:
    pass

@decorator
class demo2:
    pass

# 实例化两个demo1类型的对象,输出两个对象的id是相同的,单例模式实现
t1 = demo1()
t2 = demo1()
print(id(t1),id(t2))

# 实例化两个demo2类型的对象,输出两个对象的id是相同的,单例模式实现,其余要实现单例模式的类只要加上装饰器便可
t21 = demo2()
t22 = demo2()
print(id(t21),id(t22))
复制代码
2006092685552 2006092685552
2006092688128 2006092688128
复制代码
# 多个装饰器嵌套
#装饰器1
def decorator1(func):
    def inner():
        print('装饰器1')
        func()
        print('装饰器1')
    return inner

# 装饰器2
def decorator2(func):
    def inner():
        print('装饰器2')
        func()
        print('装饰器2')
    return inner

# 先使用装饰器1对demo进行装饰,再使用装饰器2对demo进行装饰
# 等同于 demo = decorator1(demo),demo = decorator2(demo)
@decorator2
@decorator1
def demo():
    print('demo函数')
demo()
复制代码
装饰器2
装饰器1
demo函数
装饰器1
装饰器2
复制代码

总结

  • 装饰器本质上是一个python函数,它可让其余函数在不作任何代码变更的前提下增长额外的功能,装饰器的返回值也是一个函数对象
  • python内置的三个装饰器:staticmethod,classmethod和property
    • staticmethod:把类中的方法定义为静态方法,使用staticmethod装饰的方法可使用类或者类的实例对象来调用,不须要传入self
    • classmethod:把类中的方法定义为类方法,使用classmethod装饰的方法可使用类或者类的实例对象来调用,并将该class对象隐式的做为第一个参数传入
    • property:把方法变成属性
  • 三种内置装饰器之后再详述
相关文章
相关标签/搜索