类装饰器的运作机制
装饰器是一种复合函数,如果需要用类来修饰函数,则必须在语法中,类可以这样运行
ClassName()
默认就会调 类内的 init 函数,这一点可以试验。在 python3的版本,所有类定义,无论有没有继承 object
都是属于新式类,因而隐含地具有一些默认方法
通过 打印 对象的 dir() 方法可以列出所有默认的方法。
特征: 以 <name> 命名
这种风格是python遵守的协议。
这些方法大部分是可以覆盖写的。一般情况下不需要去关心它,知道不得不关心的时候,我们可以翻到手册一看究竟
['__module__', '__init__', '__dict__', '__weakref__', '__doc__', '__new__', '__repr__', '__hash__', '__str__', '__getattribute__', '__setattr__', '__delattr__', '__lt__', '__le__', '__eq__', '__ne__', '__gt__', '__ge__', '__reduce_ex__', '__reduce__', '__subclasshook__', '__init_subclass__', '__format__', '__sizeof__', '__dir__', '__class__']
以上的 <className> 并非所有,常见的还有
__setattr__
__getattr__
__getitem__
__new__
__call__
__len__
__enter__
__exit__
等等
我们这里只关心模拟可调用对象的 __call__
因为装饰器一连环函数嵌套,如果要用一个函数装饰一个函数,那么,这个函数就是需要能接收一个函数对象作为参数,同时返回的对象也是可调用对象。否则,最外层的函数无法进行 () 运算。——我们把 () 不不看成一个特定的语法,而是看成可调用运算——对于装饰的语义更好理解
类似的,使用类对象修饰一个函数只需要把它定义为可调用对象。
即可以做如下操作的对象
a = A()
a() # 正确,将调用事先定义好的 __call__ 方法
A 定义:
class A(object):
def __call__(self, *args, **kwargs):
print("xXXXXOOOO")
但是以上的 A对象还无法装饰任何东西
deco_a = A()
@deco_a
def foo():
pass
运行会报错。需要在 __call__ 里做一些操作,具体来说和 函数装饰器类似
以下是一个类装饰器的例子
class MyHook(object):
def __call__(self, *args, **kwargs):
def deco(func):
print("abcdefg")
return func
return deco # 返回一般的函数对象可以完成装饰目的
网友评论