Python类及元类的创建流程 代码 运行结果 再看type和object的关系和约定 type和object具有的方法不一样 看代码和运行结果,可以完全理解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) 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)
运行结果
0 >> > MetaCls 0
1 >> > MetaCls 3
== == == == 1 == == == ==
2 >> > Pa 4
3 >> > Pa 7
4 >> < class '__main__.MetaCls' > __new__ 2 args Pa ( ) { '__module__' : '__main__' , '__qualname__' : 'Pa' , '__init__' : < function Pa. __init__ at 0xf62558 > , '__new__' : < function Pa. __new__ at 0xb9d520 > , '__classcell__' : < cell at 0xe00998 : empty> } kwagrsMetaCls __new__ 12179720 MetaCls __mro__ ( < class '__main__.MetaCls' > , < class 'type' > , < class 'object' > )
5 >> > < class '__main__.Pa' > __init__ 1 MetaCls __init__ 16757312
== == == == 2 == == == ==
6 >> > < class '__main__.Pa' > __new__ 6 args 10000 kwagrsPa __new__ 16757312 Pa __mro__ ( < class '__main__.Pa' > , < class 'object' > )
7 >> > < __main__. Pa object at 0x926870 > __init__ 5 Pa __init__ 9594992
8 >> > 8 < class '__main__.Pa' >
9 >> > 9 10000 son 9594992
10 >> > 10
4 >> < class '__main__.MetaCls' > __new__ 2 args meta ( ) { } kwagrsMetaCls __new__ 12179720 MetaCls __mro__ ( < class '__main__.MetaCls' > , < class 'type' > , < class 'object' > )
5 >> > < class '__main__.meta' > __init__ 1 MetaCls __init__ 11834720 metaclass < 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' > ,)
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的执行过程。再补充几点,
__new__不一定需要重写。 元类可以继承于object或者type或者其他类。如果没有显式的写成父类,默认是继承于object。 如果元类要调用父类的__new__和__init__,传递的参数要和父类方法的一致。注意:type和object中的方法和参数是不一定相同,比如__new__的参数。官方文档对object的说明,官方文档对type的说明 object没有__call__。