============Meta_new==============
meta <class '__main__.Meta'>
class name Foo
base classes (<type 'object'>,)
class attrs {'__module__': '__main__', '__metaclass__': <class '__main__.Meta'>, '__new__': <function __new__ at 0x1091ad578>, '__init__': <function __init__ at 0x1091b9578>}
=============Meta_new============
============Meta_init============
class obj <class '__main__.Foo'>
class name Foo
base classes (<type 'object'>,)
class attrs {'__module__': '__main__', '__metaclass__': <class '__main__.Meta'>, '__new__': <function __new__ at 0x1091ad578>, '__init__': <function __init__ at 0x1091b9578>}
============Meta_init===========
=============Meta_call==========
class obj <class '__main__.Foo'>
<class '__main__.Foo'>
Foo.__new__
Foo.__init__
=============Meta_call==========
<class '__main__.Foo'>
Foo.__new__
Foo.__init__
<__main__.Foo object at 0x1091b6910>
使用metaclass的时候可以使用metaclass的
__new__
和__init__
去改变所定义的类的相关属性,因为这两个方法是在类定义的时候被调用,他们所需的参数也与使用type(name, bases, dict)
动态声明类相同。而是用metaclass的__call__
可以影响我们所声明的类产生实例的过程,因为当我们使用class_name()去产生实例的时候,相当于call了这个class,而这个class又是metaclass的实例,所以其实调用了metaclass的call注意: 通过
super
来调用父类的__new__
时,第一个参数需要是该class,这点是不同于调用__init__
等其他父类方法的。因为__new__
是个静态方法。还有一个小问题就是当父类是object的时候,也就是调用object.__new__()
只传一个cls参数就可以了,至于为什么,请戳here 和here。 如果你重写了__new__
而没有重写__init__
,那么给object.__new__
传额外的参数会直接报错, 如果两个都重写了会报出DeprecationWarning,可以继续运行。输出