1.元类
类似函数装饰器和类装饰器允许我们拦截及扩建函数调用以及类实例创建调用,元类允许我们拦截和扩展类创建。
具体实现方式:它们提供了一个API以插入在一条class语句结束时运行的额外逻辑,尽管是以装饰器不同的方式。
2.控制python广泛行为的各种工具
内省属性:__class__ __dict__
运算符重载:__str__ __add__
属性拦截方法:__getattr__ setattr__ __getattribute__
类特性:使用内置函数property把代码和特殊的类属性关联起来
类属性描述符:__get__ __set__ __delete__
函数装饰器和类装饰器:装饰器的特殊的@可调用语法,允许我们添加当调用一个函数或创建一个类实例的时候自动运行的逻辑。
而元类是上述这些技术的延续,它允许我们在一条class语句的末尾,插入当创建一个类对象的时候自动运行的逻辑。这个逻辑不会把类名重新绑定到一个装饰器可调用对象,而是把类自身的创建指向特定的逻辑。元类最终只是定义自动运行代码的另外一种方式。
3.元类的使用举例
由于元类在一条class语句的末尾调用,并且因为type对象的__call__分派到了__new__和__init__方法,所以我们在这些方法中提供的代码可以管理从元类创建的所以类。
>>> class MetaOne(type):
... def __new__(meta,classname,supers,classdict):
... print('In MetaOne.new:',classname,supers,classdict,sep='\n') # __new__在类被创建时就调用,而不是实例化时才调用
... return type.__new__(meta,classname,supers,classdict)
...
>>> class Eggs:
... pass
...
>>> print('making class')
making class
>>> class Spam(Eggs,metaclass=MetaOne): # 使用metaclass声明元类
... data = 1
... def meth(self,arg):
... pass
...
In MetaOne.new: # 类被创建时就输出这里的结果
Spam
(<class '__main__.Eggs'>,)
{'__module__': '__main__', '__qualname__': 'Spam', 'data': 1, 'meth': <function Spam.meth at 0x000001357BBE16A8>}
>>> X = Spam() # 类在这里才被实例化
>>> print('data:',X.data)
data: 1
>>>
上述是__new__方法证明元类用来处理类,而类用来处理实例
下面用__init__方法定制创建和初始化,证明元类也可以用作在创建时管理类的钩子。
>>> class MetaOne(type):
... def __new__(meta,classname,supers,classdict):
... print('In MetaOne.new:',classname,supers,classdict,sep='\n')
... return type.__new__(meta,classname,supers,classdict)
... def __init__(Class,classname,supers,classdict):
... print('In MetaOne init:',classname,supers,classdict,sep='\n')
... print('init class object:',list(Class.__dict__.keys()))
...
>>> class Eggs:
... pass
...
>>> print('making class')
making class
>>> class Spam(Eggs,metaclass=MetaOne): # 使用metaclass声明元类
... data = 1
... def meth(self,arg):
... pass
...
In MetaOne.new: # 打印结果证明
Spam # 类初始化方法在构建方法之后运行
(<class '__main__.Eggs'>,)
{'__module__': '__main__', '__qualname__': 'Spam', 'data': 1, 'meth': <function Spam.meth at 0x000001357BBE1840>}
In MetaOne init:
Spam
(<class '__main__.Eggs'>,)
{'__module__': '__main__', '__qualname__': 'Spam', 'data': 1, 'meth': <function Spam.meth at 0x000001357BBE1840>}
init class object: ['__module__', 'data', 'meth', '__doc__']
>>> print('making instance')
making instance
>>> X = Spam()
>>> print('data:',X.data)
data: 1
>>>
任何可调用对象都可以用作一个元类
>>> def MetaFunc(classname,supers,classdict): # 这是一个可调用对象
... print('In MetaFunc:',classname,supers,classdict,sep='\n')
... return type(classname,supers,classdict)
...
>>> class Eggs:
... pass
...
>>> print('making class')
making class
>>> class Spam(Eggs,metaclass=MetaFunc): # 使用metaclass声明元类
... data = 1
... def meth(self,args):
... pass
...
In MetaFunc: # 创建类后,并在类实例化之前执行元类
Spam
(<class '__main__.Eggs'>,)
{'__module__': '__main__', '__qualname__': 'Spam', 'data': 1, 'meth': <function Spam.meth at 0x000001357BBE1950>}
>>> print('making instance')
making instance
>>> X = Spam()
>>> print('data:',X.data)
data: 1
>>>
本书终结!!!
非常感谢您的阅读,完全理解此书的内容,代表您已入门python,欢迎在python的海洋中继续遨游~```···