python学习手册(第4版) 第三十九章 元类

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的海洋中继续遨游~```···

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值