小测例:Python装饰器的4种类型

本文是在参考 python装饰器的4种类型:函数装饰函数、函数装饰类、类装饰函数、类装饰类 的基础下,根据自己的理解进行了补充和拓展。如有问题,欢迎指正!

0.问题场景

假设我现在要做两件事:

  1. 打印方法名,然后相加
  2. 打印方法名,然后相减

发现两件事分别包含了2个功能,并且其中一个都是打印方法名,为了避免重复代码,我将 “打印方法名” 这个功能抽象出来,变成装饰器,然后分别戴在 “相加” 这个功能和 “相减” 这个功能的头上。

如此就分解成了三件事,而每件事都只需专心实现一个功能。

以下就是在这个场景下,装饰器的4种实现方式:

1. 函数装饰函数

  • decorator 是 函数
  • 传进 decorator 的参数 是 被装饰函数
  • 传进 decorator 内函数的参数 是 被装饰函数的参数
  • decorator 内函数的返回值 是 被装饰函数的返回值
  • decorator 的返回值 是 内函数
'函数装饰函数func'
def wrapFun(func):
    def inner(*args, **kwargs):
        print('实现功能1:打印函数名', func.__name__)
        r = func(*args, **kwargs)
        return r
    return inner

@wrapFun
def foo(a, b):
    print('实现功能2: 相加=', a+b)
    return a+b

@wrapFun
def bar(a, c):
    print('实现功能3:相减=', a-c)
    return a-c
    
    
foo(a=10, b=3)
print("--------")
bar(a=10, c=5)
实现功能1:打印函数名 foo
实现功能2: 相加= 13
--------
实现功能1:打印函数名 bar
实现功能3:相减= 5

结果发现:装饰器函数 wrapFun 实现的是功能1,所以

  • 被装饰函数 foo会同时实现 装饰器的功能1 和 自身的功能2
  • 被装饰函数 bar会同时实现 装饰器的功能1 和 自身的功能3

2. 函数装饰类

  • decorator 是 函数
  • 传进 decorator 的参数 是 被装饰类
  • 传进 decorator 内函数的参数 是 被装饰类的实例化/初始化参数
  • decorator 内函数的返回值 是 被装饰类的实例化/初始化对象
  • decorator 的返回值 是 内函数
'函数装饰类cls'
def wrapClass(cls):
    def inner(*args, **kwargs):
        print('实现功能1:打印类名', cls.__name__)
        return cls(*args, **kwargs)
    return inner

@wrapClass
class FooBar():
    def __init__(self, a):
        self.a = a
        
    def func2(self, b):
        print('实现功能2: 相加=', self.a+b)
        return self.a+b
    
    def func3(self, c):
        print('实现功能3:相减=', self.a-c)
        return self.a-c
        
#装饰器功能在初始化类时执行    
obj = FooBar(10)
print('----')
obj.func2(2)
print('----')
obj.func3(3) 
实现功能1:打印类名 FooBar
----
实现功能2: 相加= 12
----
实现功能3:相减= 7
@wrapClass
class Foo():
    def __init__(self, a):
        self.a = a
        
    def func2(self, b):
        print('实现功能2: 相加=', self.a+b)
        return self.a+b
    
@wrapClass
class Bar():
    def __init__(self, a):
        self.a = a
        
    def func3(self, c):
        print('实现功能3:相减=', self.a-c)
        return self.a-c

     
obj1 = Foo(10)
print('----')
obj1.func2(2)
print('========')
obj2 = Bar(10)
print('----')
obj2.func3(3) 
实现功能1:打印类名 Foo
----
实现功能2: 相加= 12
========
实现功能1:打印类名 Bar
----
实现功能3:相减= 7

结果发现:装饰器函数 wrapFun 实现的是功能1,

  • 被装饰类会在对象实例化/初始化的时候实现 装饰器的功能1, 然后正常调用方法实现自身的功能

3. 类装饰函数

  • decorator 是
  • 实例化 decorator 的初始参数 是 被装饰函数
  • decorator 内部方法的参数 是 被装饰函数的参数
  • decorator 内部方法的返回值 是 被装饰函数的返回值
'类装饰函数func'
class ShowFunName():
    def __init__(self, func):
        self._func = func
        
    def __call__(self, *args, **kwargs):
        print('实现功能1:打印函数名', self._func.__name__)
        r = self._func(*args, **kwargs)
        return r
    
@ShowFunName
def foo(a, b):
    print('实现功能2: 相加=', a+b)
    return a+b

@ShowFunName
def bar(a, c):
    print('实现功能3:相减=', a-c)
    return a-c


foo(a=10, b=3)
print("--------")
bar(a=10, c=5) 
实现功能1:打印函数名 foo
实现功能2: 相加= 13
--------
实现功能1:打印函数名 bar
实现功能3:相减= 5

结果发现:装饰器类ShowFunName 的内部方法是实现功能1,

  • 被装饰函数 执行的时候会先实现 装饰器的功能1, 然后执行自身的功能

4. 类装饰类

  • decorator 是
  • 实例化 decorator 的初始参数 是 被装饰类
  • decorator 内部方法的参数 是 被装饰类的实例化/初始化参数
  • decorator 内部方法的返回值 是 被装饰类已经实例化/初始化了的对象
'类装饰类cls'
class ShowClassName(object):
    def __init__(self, cls):
        self._cls = cls
        
    def __call__(self, *args, **kwargs):
        print('实现功能1:打印类名', self._cls.__name__)
        return self._cls(*args, **kwargs)

@ShowClassName
class FooBar(object):
    def __init__(self, a):
        self.a = a

    def func2(self, b):
        print('实现功能2: 相加=', self.a+b)
        return self.a+b
    
    def func3(self, c):
        print('实现功能3:相减=', self.a-c)
        return self.a-c

obj = FooBar(10)
print('----')
obj.func2(3)
print('----')
obj.func3(3)
实现功能1:打印类名 FooBar
----
实现功能2: 相加= 13
----
实现功能3:相减= 7
@ShowClassName
class Foo():
    def __init__(self, a):
        self.a = a
        
    def func2(self, b):
        print('实现功能2: 相加=', self.a+b)
        return self.a+b
    
@ShowClassName
class Bar():
    def __init__(self, a):
        self.a = a
        
    def func3(self, c):
        print('实现功能3:相减=', self.a-c)
        return self.a-c

     
obj1 = Foo(10)
print('----')
obj1.func2(2)
print('========')
obj2 = Bar(10)
print('----')
obj2.func3(3) 
实现功能1:打印类名 Foo
----
实现功能2: 相加= 12
========
实现功能1:打印函数名 Bar
----
实现功能3:相减= 7

结果发现:装饰器类ShowFunName 的内部方法是实现功能1,

  • 被装饰类 会在对象实例化/初始化的时候实现 装饰器的功能1, 然后正常调用方法实现自身的功能

*附

Mark 更多

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值