python 读书笔记 (七) 元类
2017-06-18 00:00
127 查看
元类
类型对象负责创建对象实例,控制对象的行为。那么类型对象又由谁来创建呢?
———元类,也就是类型的类型
关键字class会被编译成元类创建类型对象的指令
正是因为 class 和def 一样是指令,我们可以在任何地方创建类型对象
现在可以理清几者之间的关系, 以及创建顺序类。
class = metaclass(....) # 元类创建类型
instance = class(...) # 类型创建实例
instance.__class__ is class # 实例的类型
class.__class__ is metaclass # 类型的类型
metaclass
除了使用默认元类type 以外, 还可以用 __metaclass__ (python3 使用metalcass 关键字)属性指定自定义元类, 以便对类型对象创建过程进行干预。
当解释器创建类型对象时, 会按照以下顺序查找__metaclass__属性
class.__metaclass__ --> bases.__metaclass__ --> module.__metaclass__ -> type
这也是为什么在模块中可以用__metaclass__为所有类型指定默认元类的缘故
虽然惯例将元类写成type的派生类,但是也可以用函数替代
静态类:不允许创建实例,通常作为工具类存在。
密封类: 禁止被继承
类型对象负责创建对象实例,控制对象的行为。那么类型对象又由谁来创建呢?
———元类,也就是类型的类型
>>> 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
相关文章推荐
- python 学习笔记 元类 ORM
- python笔记:深刻理解Python中的元类(metaclass)
- 【Python】Python学习笔记——读书心得
- 读书笔记--python数据可视化--002_读取Excel文件数据
- Python 读书笔记 (2)
- Python 读书笔记 (1)
- python 读书笔记 (十二) 进程通信
- python cookbook 读书笔记1(字符串处理1)
- 【Python】学习笔记——-8.6、面向对象高级编程:6.使用元类
- 【集体智慧编程】【Python3】【读书笔记1】提供推荐
- python machine learning 读书笔记1——Mac OS环境搭建技巧
- python 读书笔记 (六) 异常描述符
- python 学习笔记——python metaclass 元类
- python学习笔记1-元类__metaclass__
- 初学Python的学习笔记11----使用元类、错误处理和调试
- 读书笔记--用Python写网络爬虫01--网络爬虫简介
- 读书笔记-----Oracle字符处理函数列表
- C读书笔记
- python学习笔记1
- 再谈读书笔记