Python类及元类的创建流程
- 代码
- 运行结果
- 再看type和object的关系和约定
- type和object具有的方法不一样
- 看代码和运行结果,可以完全理解python的执行过程。再补充几点,
代码
python">class MetaCls(type):print('0>>>', 'MetaCls', 0)def __init__(self, name, bases=None, dict=None):print('5>>>',self, '__init__',1)print(' MetaCls','__init__',id(self))super(MetaCls,self).__init__(name, bases, dict)def __new__(cls, *args, **kwagrs):print('4>>',cls, '__new__',2)print(' args',*args)print(' kwagrs',**kwagrs)print(' MetaCls','__new__',id(cls))print(' MetaCls','__mro__', MetaCls.__mro__)return super(MetaCls, cls).__new__(cls, *args, **kwagrs)print('1>>>', 'MetaCls',3) print("========1========")class Pa(metaclass=MetaCls):print('2>>>', 'Pa',4)def __init__(self, num):self.num = numprint('7>>>', self, '__init__',5)print(' Pa','__init__',id(self))def __new__(cls, *args, **kwagrs):print('6>>>', cls, '__new__',6)print(' args',*args)print(' kwagrs',**kwagrs)print(' Pa','__new__',id(cls))print(' Pa','__mro__',Pa.__mro__)return super(Pa, cls).__new__(cls)# return object.__new__(cls)print('3>>>', 'Pa',7)print("========2========")son = Pa(10000)
print('8>>>',8)
print(' ',type(son))
print('9>>>',9)
print(' ',son.num)
print(' son',id(son))
print('10>>>',10)
metaclass = MetaCls('meta',(),{})
print(' metaclass', metaclass)
运行结果
python">0>>> MetaCls 0
1>>> MetaCls 3
========1========
2>>> Pa 4
3>>> Pa 7
4>> <class '__main__.MetaCls'> __new__ 2args Pa () {'__module__': '__main__', '__qualname__': 'Pa', '__init__': <function Pa.__init__ at 0xf62558>, '__new__': <function Pa.__new__ at 0xb9d520>, '__classcell__': <cell at 0xe00998: empty>}kwagrsMetaCls __new__ 12179720MetaCls __mro__ (<class '__main__.MetaCls'>, <class 'type'>, <class 'object'>)
5>>> <class '__main__.Pa'> __init__ 1MetaCls __init__ 16757312
========2========
6>>> <class '__main__.Pa'> __new__ 6args 10000kwagrsPa __new__ 16757312Pa __mro__ (<class '__main__.Pa'>, <class 'object'>)
7>>> <__main__.Pa object at 0x926870> __init__ 5Pa __init__ 9594992
8>>> 8<class '__main__.Pa'>
9>>> 910000son 9594992
10>>> 10
4>> <class '__main__.MetaCls'> __new__ 2args meta () {}kwagrsMetaCls __new__ 12179720MetaCls __mro__ (<class '__main__.MetaCls'>, <class 'type'>, <class 'object'>)
5>>> <class '__main__.meta'> __init__ 1MetaCls __init__ 11834720metaclass <class '__main__.meta'>
再看type和object的关系和约定
>>> object.__bases__
()>>> object.__bases__.__bases__
Traceback (most recent call last):File "<stdin>", line 1, in <module>
AttributeError: 'tuple' object has no attribute '__bases__'>>> object.__bases__.__class__
<class 'tuple'>>>> object.__class__
<class 'type'>>>> type.__bases__
(<class 'object'>,)>>> type.__class__
<class 'type'>>>> ().__bases__
Traceback (most recent call last):File "<stdin>", line 1, in <module>
AttributeError: 'tuple' object has no attribute '__bases__'>>> ().__class__
<class 'tuple'>>>> ().__class__.__bases__
(<class 'object'>,)
python中type和object的关系图" />
type和object具有的方法不一样
>>> dir(type)
['__abstractmethods__', '__annotations__', '__base__', '__bases__', '__basicsize__', '__call__', '__class__', '__delattr__', '__dict__', '__dictoffset__', '__dir__', '__doc__', '__eq__', '__flags__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__instancecheck__', '__itemsize__', '__le__', '__lt__', '__module__', '__mro__', '__name__', '__ne__', '__new__', '__or__', '__prepare__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__ror__', '__setattr__', '__sizeof__', '__str__', '__subclasscheck__', '__subclasses__', '__subclasshook__', '__text_signature__', '__weakrefoffset__', 'mro']>>> dir(object)
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
python_137">看代码和运行结果,可以完全理解python的执行过程。再补充几点,
- __new__不一定需要重写。
- 元类可以继承于object或者type或者其他类。如果没有显式的写成父类,默认是继承于object。
- 如果元类要调用父类的__new__和__init__,传递的参数要和父类方法的一致。注意:type和object中的方法和参数是不一定相同,比如__new__的参数。官方文档对object的说明,官方文档对type的说明
- object没有__call__。
- __new__中一定有return返回类或实例,__init__中没有return。
- 推荐阅读,其中核心之一是
class Foo(object, metaclass=MyMetaclass, kwarg1=value1):
…
它在元类中转换为
def new(cls, clsname, bases, dct, kwargs1=default):
…