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还是优先提倡的。

猜你喜欢

转载自blog.csdn.net/oqqZhe1234/article/details/95944314