欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Python 中的元类(metaclass)与抽象基类(ABCs)

程序员文章站 2022-06-16 23:33:30
...

元类:

元类的细致解释完全可以参考这篇博文:http://blog.jobbole.com/21351/

这本是一篇 stack overflow 上的问答,被这位博主翻译成了中文。讲的非常细致周全,这里就不再引用了,仅记录几个点:

  • 总之,元类是一个比较高级而晦涩的概念,极少用到。所以即使不明白,或者明白了但不会用都没大妨碍
  • 元类其实就是类的类,或者说,就像类被调用可以产生实例一样,元类用来产生类
  • 新式类的元类是 type,type 既是一个工厂函数又扮演着元类的角色,如下所示:
>>> type
<class 'type'>
>>> type(object)
<class 'type'>
>>> type(object) is type
True

这也就是在自定义元类的时候会看到 class MyMetaClass(type): 继承自 type 的原因

  • type(cls_name, cls_parents, cls_attr) 可以这样使用 type 来生成一个类
  • 元类的 __init__(),__new__() 方法比上面的 type 只多接受一个 cls 参数
  • 其实任意可调用对象都可以充当元类(赋值给 __metaclass__),不过使用类有额外的好处
  • __metaclass__ 属性的搜索顺序是这样的:先寻找类属性、然后是祖先类属性,没有就去模块或全局里找 __metaclass__ 变量。还找不到那这就是个传统类,传统类的元类是 types.ClassType

抽象基类:

同样一个不常用的东西,所以也同样的仅记录一些知识点在这里:

  • 抽象基类是用来继承的,abc 模块提供一个元类(ABCMeta)和两个装饰器(@abstractmethod 、 @abstractproperty)来自定义抽象基类
  • 使用了上面两个装饰器的基类不可实例化,并且被继承的时候必须在子类里覆盖这些抽象方法(非抽象方法、属性可以不用覆盖)
  • 抽象基类可以通过继承、或者ABCMeta的.register()方法来注册:
>>> help(abc.ABCMeta.register)
Help on function register in module abc:

register(cls, subclass)
    Register a virtual subclass of an ABC.
    
    Returns the subclass, to allow usage as a class decorator.
  • 容器和迭代器类被ABCs化,数值类型也被ABCs化了。这些基类可以在 collections 和 numbers 模块里找到

抽象基类的一些参考:

转载于:https://my.oschina.net/lionets/blog/191107