当前位置:   article > 正文

python中的元类

python中的元类

       python编程一般说到元类和元编程,就瞬间高大上起来了,似乎它们是什么很高级的概念和奇技淫巧一样,其实它们是非常普通的概念,在python的各种框架实现里面被广泛使用,python程序员如果对元类感觉到没把握那是行不通的。

        正如类是类的实例的工厂,元类则是类的工厂。不过这两种关系还是有所不同,类是类的实例的模版,但元类不是类的模版,元类更像一个纯粹的类的组装工厂。类里面有两个特殊方法与产生一个类的实例有关,__new__和__init__,前者用于产生一个类的实例的初始版本,后者用于对类的实例的初始版本做初始化,元类作为类的工厂,同样的具有这两个方法,意义差不多。

      上面说了类是类的实例的模板,所以你看类的__new__被定义为一个绑定的类方法,类本身是作为方法的第一个参数,一般命名为cls,一般情况下,__new__不需要其他的参数,__new__根据cls来产生一个实例,__new__返回产生的实例,也有tuple等少数例外__new__需要额外的参数,绝大多数情况是不需要的。但元类并不是类的模板,虽然它的__new__方法也一样是个绑定的类方法,但它还固定需要另外三个参数name, bases, attr_dict,分别代表类的名字、类的超类的元组和类的属性的字典,它们均取自类的类体。元类的__new__方法拿到这三个值之后,把它们组装成一个类对象,并且作为返回值返回。

       type是所有元类的基类,我们自己定义的元类都直接/间接得继承自type。

       下面给出一个示例代码:

  1. import sys, collections
  2. class MyMeta(type):
  3. @classmethod
  4. def __prepare__(this, name, bases):
  5. return collections.OrderedDict()
  6. def __new__(this, name, bases, attrs, **kwargs):
  7. cls = super().__new__(this, name, bases, attrs, **kwargs)
  8. return cls
  9. def __init__(cls, name, bases, attrs, **kwargs):
  10. super().__init__(name, bases, attrs, **kwargs)
  11. class x(metaclass=MyMeta):
  12. def f3(self):pass
  13. def f2(self):pass
  14. def f1(self):pass

       可以在__new__或者__init__里面添加代码,根据自己的意图,在产生类对象之前做一些干预,在产生类对象之后,对类做一些改变。__prepare__方法是一个可选方法,实现了此方法,该方法返回的字典将作为__new__和__init__的attrs参数。

      上面的例子,元类的作用是让类x中定义的三个函数在类的__dict__中保持类中定义的顺序,当然现在高版本的python本身就已经可以保证这一点,但是在python2.x中是不能保证的,这里也只是举例来说明元类的作用。

      元类和元编程很简单吧,通过定义一个元类,我们可以对定义一个类施展更多的手段,带来了很多的灵活性,但同时也带来了复杂性,通过元类的一番改头换面,可能最后生成的类与我们在类的类体定义中看到的样子会有出入,违背了所见即所得的原则,对于看别人代码的人来说,有时候,这是令人不舒适的。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/490024
推荐阅读
相关标签
  

闽ICP备14008679号