欢迎来到簟纹灯影的博客

人生三从境界:昨夜西风凋碧树,独上高楼,望尽天涯路。 衣带渐宽终不悔,为伊消得人憔悴。 众里寻他千百度,蓦然回首,那人却在灯火阑珊处。

浅谈元类(个人理解)

元类

什么叫元类

我们知道在python中一切皆对象(object),那么所以有的对象都成了object的子类,那么object类又是由谁创建的呢?

实际上,能够创建类的类,叫元类。还有一个概念就是:元类创建了object类,同时又是object类的子类(这是什么鬼?我们就不去考虑这个逻辑了,已经完美解决了先有鸡还是先有蛋的问题了)。

元类实际还是所有类的创建者,即使所有类(包括元类自己)都是object的子类,他们的关系如下:

Interesting......

class的底层

当我们使用class 类名的时候,就会把类构造出来。实际上是元类实例化产生类,隐藏的语法如下:

type(name, bases, dict),传入三个参数时,代表class语句的动态形式,name字符串即类名并且会成为__name__属性;bases元组列出基类并且会成为__bases__属性;而dict字典代表类的名称空间即__dict__属性。

例如,以下两条语句会创建相同的type对象:

class A:
    a = 1
    
A = type('A',(object,), dict(a = 1))

使用type控制类的产生

自定义元类:继承type:

class Mymeta(type):
    def __init__(self, name, bases, dic):
        '''控制类的产生,在__new__之后'''
        #self 是A这个类(type的对象)
        #在这个位置,其实self也就说A这个类,内部已经有东西了,名称空间已经有东西了
        #所以在这个地方,可以通过dic来判断名称空间
        #也可以直接通过self.__dict__/self.属性 来判断
        a = self.__dict__.get('attr').get('name')  # 后面做了修改
        if not a:
            raise Exception("没有name 属性")
        super().__init()
        
    def __new__(cls, name, bases, dic):
        '''最根本上控制类产生,其实本质最根上也不是它,是type的__call__,但是我们控制不了了'''
        dic2 = {'attr' : {}}
        for k,v in dic.items():
            if not k.startswith('__'):
                dic2['attr'][k] = v
            else:
                dic2[k] = v
        return type.__new__(cls, name, bases, dic2)  # 必须返回

    def __call__(self, *args, **kwargs):
        '''控制类对象的产生'''
        print(args,kwargs)
        obj = self.__new__(self)
        obj.__init__(*args, **kwargs)
        return obj   # 必须返回一个类的对象


class A(metaclass=Mymeta):
    name = 'ddd'

    def __init__(self, id):
        self.id = id

    def __repr__(self):
        return 123

a = A(111)

元类里最重要的有三个魔术方法:

  • __init__:控制类的产生,在__new__之后
  • __call__:控制类对象的产生
  • __new__:最根本上控制类产生,其实本质最根上也不是它,是type的__call__,但是我们控制不了了

更详细的内容会在将来的某一天更新...

posted @ 2019-09-16 18:58  簟纹灯影  阅读(188)  评论(0编辑  收藏  举报