1、首先我们要知道:
对象是由类创建的,而类是由type类创建的
所以创建类有两个方法:
class Foo(object): pass# 类名,继承关系,属性Foo = type('Foo',(object,),{})
上面第一种方法也是默认用type来创建类的,我们就可以理解为类其实就是type的一个对象
当类名()这样加括号的时候,会首先调用type的_ _call_ _方法,在这个方法里会调用类的_ _new_ _方法来创建一个裸着的对象,也就是开辟内存空间,但是没有任何东西,继而继续调用执行类的_ _init_ _方法来给对象封装一些属性
补充一下:对象()这样加括号就会调用类的_ _call_ _方法
2、metaclass就可以指定我们自定义的type类,当用类名()时就会从我们定义的metaclass参数值的类中调用_ _call_ _方法,要依次调用_ _new_ _和_ _init_ _方法,返回对象
这样做的一个好处是我们在实例对象时先是_ _new_ _方法再是_ _init_ _方法,用了我们自定义type类的时候我们就可以在new方法和init方法之间就可以做一些操作了
class MyType(type): def __init__(self,*args,**kwargs): super(MyType,self).__init__(*args,**kwargs) def __call__(self, *args, **kwargs): obj = self.__new__(self,*args, **kwargs) # object.__init__(....) obj.__init__(*args, **kwargs) # self.__init__(obj,*args, **kwargs) return objclass Foo(object,metaclass=MyType): def __init__(self): print('xxx')# 1. 类是MyType的对象。由MyType(...)# 2. Foo()obj = Foo()print(obj)
注意在python2中metaclass的写法不同:
# python3class Foo(object,metaclass=MyType): pass # python2class Foo(object): __metaclass__ = MyType
补充:
metaclass的作用:就是用来指定当前类由谁创建,对派生类也是一样的,也就是当父类指定了metaclass以后,它的派生类也得由metaclass指定的类来创建
第二种指定metaclass类的方法
class MyType(type): def __init__(self, *args, **kwargs): super(MyType, self).__init__(*args, **kwargs) def __call__(cls, *args, **kwargs): print('xxxx') return super(MyType, cls).__call__(*args, **kwargs)# Foo继承的类是由MyType创建的,所以Foo类继承这个创建出来的类,那Foo的metaclass也是MyTypeclass Foo(MyType('Base', (object,), {})): passobj = Foo()
第三种指定metaclass类的方法
class MyType(type): def __init__(self, *args, **kwargs): super(MyType, self).__init__(*args, **kwargs) def __call__(cls, *args, **kwargs): return super(MyType, cls).__call__(*args, **kwargs)def with_metaclass(base): return MyType('XX', (base,), {})# Foo继承的是with_metaclass函数的返回值,返回值仍是由MyType创建的一个类# 所以Foo作为创建出来的类的派生类,Foo的metaclass也是MyTypeclass Foo(with_metaclass(object)): pass
总结:类和对象加括号时的流程
类是type创建的,所以说类就是type的一个对象,而type又是由object创建的
我们创建类的时候实际上就是写type(),那这样的话就会调用object的__call__方法,在这个方法中会调用type的__new__和__init___方法
我们实例类对象时就是写类(),那这样的话就会调用type的__call__方法,在这个方法中会调用类的__new__和__init__方法