`__new__`中的`super()`是什么?

q09*_*987 12 python python-3.x

注意:使用Python的flyweight实现的一部分

import weakref

class CarModel:
    _models = weakref.WeakValueDictionary()

    def __new__(cls, model_name, *args, **kwargs):
        model = cls._models.get(model_name)
        if not model:
            model = super().__new__(cls)
            cls._models[model_name] = model    
        return model

    def __init__(self, model_name, air=False):
        if not hasattr(self, "initted"):
          self.model_name = model_name
          self.air = air
          self.initted=True
Run Code Online (Sandbox Code Playgroud)

问题1>什么super()意思?这是否意味着父类CarModel

问题2>我也很难理解该功能的__new__工作原理?具体来说,以下行.

model = super().__new__(cls)
Run Code Online (Sandbox Code Playgroud)

说明__new__:

构造函数被调用__new__而不是__init__,并且只接受一个参数,即正在构造的类(在构造对象之前调用它,因此没有自参数).它还必须返回新创建的对象.

Dol*_*000 17

super()本身的开头只是简写super(A, B),A代码出现的类在哪里,并且B是代码出现的函数的第一个参数; 所以在你的特定情况下,super().__new__(cls)扩展为super(CarModel, cls).__new__(cls).

反过来,super(T, O)返回一个"超级对象".要了解超级对象的作用,您需要了解实例和类的属性引用如何在Python中工作.

假设没有__getattr____getattribute__涉及方法,引用A对象的属性O(即,评估O.Agetattr(O, "A"))继续执行以下步骤:

  1. 如果"A"O实例dict(O.__dict__)中定义,则直接返回该dict上的值,就像它一样.
  2. 否则,O依次检查方法解析顺序中的每个类,"A"在每个单词中查找.如果找到,请调用该值D.
  3. 如果D反过来,没有定义__get__,则返回原样.但是,如果确实如此,则将D其称为"描述符",并将其__get__方法O作为第一个参数调用,并type(O)作为第二个参数调用.

类的属性引用大致相同,用实例引用的类替换,但有以下区别:

  • 第1步不适用.
  • __get__使用None第一个参数调用该方法,并将该类作为第二个参数调用.

Python使用描述符来实现诸如实例方法,类方法,静态方法和属性之类的东西.

super(T, O)然后,使用一个(内置)对象创建一个超级对象,该对象具有一个__getattribute__方法,该方法在其上的每个属性引用上调用,并在MRO中的T之后的唯一类的查找中查找该属性O.它随后找到的值,它__get__像往常一样调用.

这个过程有点复杂,所以作为一个例子,这是它如何适用于您的具体情况.由于CarModel它是定义的,它的MRO是[CarModel, object].

  1. super().__new__(cls)super(CarModel, cls).__new__(cls)如上所述,扩展到.
  2. super(CarModel, cls)被评估以产生超级对象S.
  3. 蟒获取属性"__new__"S(调用相当于getattr(S, "__new__")在Python代码).
  4. 既然S是在CarModel类上创建的,它会考虑CarModelMRO中的类CarModel,并"__new__"object类本身的dict中找到.它的值是一个静态方法,它有一个__get__方法,用参数None和方法调用cls.由于__new__是一个静态方法,它的__get__方法只是原样返回函数,未经修改.因此,super(CarModel, cls).__new__恰恰相同object.__new__.
  5. 在最后一步(即,object.__new__)中获得的函数使用cls参数调用,其中cls可能CarModel最终是CarModel类的新实例.

我希望这完全可以理解.

(为了完整起见,应该提到的是,类__new__上的实际函数object实际上并不是静态方法,而是一个根本没有__get__方法的特殊内置函数,但由于__get__静态方法上的方法只返回他们定义的功能,效果是一样的.)


Amb*_*ber 5

super() 用于引用超类(即您要从其子类化的父类)。

__new__ 是一个被调用以创建类的新实例的方法(如果已定义)。

  • 在`super(class1, class2)`中,`super`如何使用`class1`和`class2`? (2认同)