Python类的__new()__ 方法 VS metaclass的__new()__ 方法
总起来说,两者的区别是:1.作用不同:类的__new()__ 方法是返回一个对象;而metaclass是返回一个类(其实类也是type的一个对象,万物皆为对象啊)2:时间不同:前者在生成对象的时候调用,后者在定义类的时候调用。
>>> class Animal(object): ... def __init__(self): ... pass ... def __new__(cls, *args, **kw): ... print(cls, args, kw) ... result = super().__new__(cls) ... print(result) ... return result ... >>> class Cat(Animal): ... name = my name is cat. ... def __init__(self, name, weight): ... self.name = name ... self.weight = weight ... >>> Cat(huahua, 30) <class __main__.Cat> (huahua, 30) { } <__main__.Cat object at 0x013A3C90> <__main__.Cat object at 0x013A3C90>
从上面代码中可以看到,当最后输入Cat(‘huahua’, 30)时,类Animal里面的__new()__才开始起作用。我们再看下面一个例子:
>>> class ListMetaclass(type): ... def __new__(cls, name, bases, attrs): ... print(cls, name, bases, attrs) ... return type.__new__(cls, name, bases, attrs) ... >>> class MyList(object, metaclass=ListMetaclass): ... name = mylist ... def fun(): ... pass ... <class __main__.ListMetaclass> MyList (<class object>,) { __module__: __ma in__, __qualname__: MyList, name: mylist, fun: <function MyList.fun a t 0x013A44B0>} >>>
-
从上面例子可以看出,当在交互命令模式下输入完成class MyList的定义后,metaclass立即起作用。 虽然两者起作用的时机上有所不同,但是仔细观察两者可以发现__new(cls,…)__的第一个参数都是<class ‘__main__.XXX’>,也就是一个类。通过该参数,结合getattr、hasattr、delattr、dir等built-in function可以修改该类的一些属性。当然,metaclass的__new()__(…, attrs)自带一个attrs参数,因此可以更方便的操作新类的属性。 类中定义__new()__的优点:通过在父类中定义__new()__,子类在生成对象的时候可以临时修改该子类的类属性(注意这里是临时! 因为每定义一个子类对象都会运行___new()__);而使用metaclass需要定义一个父类和一个metaclass,比较麻烦,代码也不简洁。 使用metaclass的优点:在定义子类的时候就执行了metaclass的__new()__,不用在每生成一个对象的时候分别再调用,比上者效率要高。虽然还得多写一个metaclass,代码也不简洁,但是metaclass还是优先提倡的。