快捷搜索: 王者荣耀 脱发

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还是优先提倡的。
经验分享 程序员 微信小程序 职场和发展