1 .所有Python的用户自定义累, 都是type这个类的实例
1
In [1]: class MyClass(object):
2
   ...:     pass
3
   ...: 
4
5
In [2]: instance = MyClass()
6
7
In [3]: type(instance)
8
Out[3]: __main__.MyClass
9
10
In [4]: type(MyClass)
11
Out[4]: type

instance 是MyClass的实例, 而MyClass不过是type的实例

2.用户自定义类, 是type类的__call__运算符重载

当定义一个类的语句结束时,真正发生的情况, 是Python调用type的__call__运算符

例如:当定义一个类时,

1
In [6]: class MyClass:
2
   ...:     data = 1
3
   ...:

python 真正执行的时下面的代码:

1
class type(classname, superClasses, attributedict)

这里class type(classname, superClasses, attributedict)就是type的__call__运算符重载,它会进一步调用:

1
type.__new__(typeclass, classname, superclasses, sttributedict)
2
type.__init__(class, classname, superclasses, attributedict)

代码验证

1
In [1]: class MyClass(object):
2
   ...:     data = 1
3
   ...: 
4
In [4]: instance = MyClass()
5
6
In [5]: instance
7
Out[5]: <__main__.MyClass at 0x7f434aa68048>
8
9
In [6]: MyClass
10
Out[6]: __main__.MyClass
11
12
In [7]: instance.data
13
Out[7]: 1
14
15
In [8]: MyClass = type("MyClass", (), {"data": 1})
16
17
In [9]: instance = MyClass()
18
19
In [10]: instance
20
Out[10]: <__main__.MyClass at 0x7f434aa2bc88>
21
22
In [11]: MyClass
23
Out[11]: __main__.MyClass
24
25
In [12]: instance.data
26
Out[12]: 1
3.metaclasstype的子类,通过替换type__call__运算符重载机制,‘metaclass’ 正常的类

一旦将一个类型的MyClass的metaclass 设置成MyMeta,MyClass就不再由原生的type创建, 而是会调用MyMeta__call__ 运算符重载

1
In [13]: class = type(classname, superclasses, attributedict)
2
变为
3
In [14]: class = MyMeta(classname, superclasses, attributedict)
  • example

    1
    class Mymeta(type):
    2
        def __init__(self, name, bases, dic):
    3
            super().__init__(name, bases, dic)
    4
            print('===>Mymeta.__init__')
    5
            print(self.__name__)
    6
            print(dic)
    7
            print(self.yaml_tag)
    8
    9
        def __new__(cls, *args, **kwargs):
    10
            print('===>Mymeta.__new__')
    11
            print(cls.__name__)
    12
            return type.__new__(cls, *args, **kwargs)
    13
    14
        def __call__(cls, *args, **kwargs):
    15
            print('===>Mymeta.__call__')
    16
            obj = cls.__new__(cls)
    17
            cls.__init__(cls, *args, **kwargs)
    18
            return obj
    19
    20
    21
    class Foo(metaclass=Mymeta):
    22
        yaml_tag = '!Foo'
    23
    24
        def __init__(self, name):
    25
            print('Foo.__init__')
    26
            self.name = name
    27
    28
        def __new__(cls, *args, **kwargs):
    29
            print('Foo.__new__')
    30
            return object.__new__(cls)
    31
    32
    33
    foo = Foo('foo')

    output:

    1
    ===>Mymeta.__new__
    2
    Mymeta
    3
    ===>Mymeta.__init__
    4
    Foo
    5
    {'__module__': '__main__', '__qualname__': 'Foo', 'yaml_tag': '!Foo', '__init__': <function Foo.__init__ at 0x7f4b540d0d90>, '__new__': <function Foo.__new__ at 0x7f4b540d0e18>}
    6
    !Foo
    7
    ===>Mymeta.__call__
    8
    Foo.__new__
    9
    Foo.__init__