本文是在参考 python装饰器的4种类型:函数装饰函数、函数装饰类、类装饰函数、类装饰类 的基础下,根据自己的理解进行了补充和拓展。如有问题,欢迎指正!
0.问题场景
假设我现在要做两件事:
- 打印方法名,然后相加
- 打印方法名,然后相减
发现两件事分别包含了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 更多: