您的位置:首页 > 编程语言 > Python开发

python 读书笔记 (七) 元类

2017-06-18 00:00 127 查看
元类

类型对象负责创建对象实例,控制对象的行为。那么类型对象又由谁来创建呢?

———元类,也就是类型的类型

>>> class Data(object): pass
...
>>> Data.__class__
<class 'type'>
>>> type.__class__                  # 最终的类型就是type, 包括type自己
<class 'type'>

关键字class会被编译成元类创建类型对象的指令

>>> Data = type('Data', (object,), {'z': 1})
>>> Data.__class__
<class 'type'>
>>> Data.__base__
<class 'object'>

>>> Data.z
1

正是因为 class 和def 一样是指令,我们可以在任何地方创建类型对象

>>> def test():
...     class Data(object): pass
...     return Data
...
>>> Data = test()
>>> Data.__name__
'Data'
>>> type(Data)
<class 'type'>
>>> Data()
<__main__.test.<locals>.Data object at 0x7f6cf5de0c88>

现在可以理清几者之间的关系, 以及创建顺序类。

class = metaclass(....) # 元类创建类型

instance = class(...) # 类型创建实例

instance.__class__ is class # 实例的类型

class.__class__ is metaclass # 类型的类型

metaclass

除了使用默认元类type 以外, 还可以用 __metaclass__ (python3 使用metalcass 关键字)属性指定自定义元类, 以便对类型对象创建过程进行干预。

class InjectMeta(type):
def __new__(cls, name, bases, attrs):
t = type.__new__(cls, name, bases, attrs)

def print_id(self):
print(hex(id(self)))

t.print_id = print_id
t.s = 'hello, world'
return t

class Data(object, metaclass=InjectMeta):
pass

# print(Data.__metaclass__)
print(Data.__class__)
print(dir(Data))
print(Data.s)
# <class '__main__.InjectMeta'>
# ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'print_id', 's']
# hello, world

当解释器创建类型对象时, 会按照以下顺序查找__metaclass__属性

class.__metaclass__ --> bases.__metaclass__ --> module.__metaclass__ -> type

这也是为什么在模块中可以用__metaclass__为所有类型指定默认元类的缘故

虽然惯例将元类写成type的派生类,但是也可以用函数替代

>>> def inject_meta(name, bases, attrs):
...     t = type(name, bases, attrs)
...     t.s = 'hello, world!'
...     return t
...
>>> class Data(object):
...     __metaclass__ = inject_meta
...
>>> Data.__metaclass__
<function inject_meta at 0x7f6cf7588048>

静态类:不允许创建实例,通常作为工具类存在。

class StaticClassMeta(type):
def __new__(cls, *args, **kwargs):
t = type.__new__(cls, *args, **kwargs)

def ctor(cls, *args, **kwargs):
raise RuntimeError('Cannot create a instance of the static class')
t.__new__ = staticmethod(ctor)

return t

class Data(object, metaclass=StaticClassMeta):
pass

if __name__ == '__main__':
Data()   # RuntimeError: Cannot create a instance of the static class

密封类: 禁止被继承

class SealedClassMeta(type):
_type = set()

def __init__(cls, name, bases, attrs):
if cls._type & set(bases):          # 判断当前类型基类是否是 sealed class
raise SyntaxError(' cannot inherit from a seal class')
cls._type.add(cls)                  # 将当前类型加入入到禁止止继承集合。
class Data(object, metaclass=SealedClassMeta):
pass

class A(Data):      # SyntaxError:  cannot inherit from a seal class
pass
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: