\`super()\` 在 __new__ 中是什么意思

新手上路,请多包涵

注意:使用 Python 的轻量级实现的一部分

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

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

问题 2> 我也很难理解函数 __new__ 是如何工作的?具体来说,如下一行。

 model = super().__new__(cls)

__new__ 的说明:

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

原文由 q0987 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 430
1 个回答

To begin with super() in itself is simply shorthand for super(A, B) , where A is the class wherein the code occurs, and B is the代码出现的函数的第一个参数;因此,在您的特定情况下, super().__new__(cls) 扩展为 super(CarModel, cls).__new__(cls)

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

Assuming no __getattr__ or __getattribute__ methods are involved, referencing attribute A on an object O (that is, evaluating O.Agetattr(O, "A") ) 通过以下步骤进行:

  1. 如果 "A"O 的实例字典( O.__dict__ )中定义,则它直接返回该字典的值。
  2. 否则,依次检查 O 的方法解析顺序中的每个类,在它们的每个字典中查找 "A" 。如果找到,调用值 D
  3. 如果 D 又没有定义 __get__ ,则按原样返回。但是,如果是这样,那么 D 被称为“描述符”,并且它的 __get__ 方法被调用 O 作为第一个参数,并且 type(O) 作为 --- 作为第二个参数。

类上的属性引用的工作方式大致相同,用类作为实例的引用,但有以下区别:

  • 第 1 步不适用。
  • __get__ 方法以 None 作为第一个参数,被引用的类作为第二个参数。

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

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

这个过程有点复杂,所以作为一个例子,下面是它在你的具体案例中的工作方式。由于 CarModel 按原样定义,其 MRO 为 [CarModel, object]

  1. super().__new__(cls) 扩展为 super(CarModel, cls).__new__(cls) ,如上所述。
  2. super(CarModel, cls) 被评估为产生一个超级对象 S
  3. Python 在 "__new__" S (相当于在 Python 代码中调用 getattr(S, "__new__") )。
  4. Since S was created on the CarModel class, it considers the classes following CarModel in the MRO of CarModel , and finds "__new__"object 类本身的字典中。它的值是一个静态方法,有一个 __get__ 方法,它使用参数 Nonecls 。由于 __new__ 是一个静态方法,它的 __get__ 方法只是按原样返回函数,未修改。因此, super(CarModel, cls).__new__object.__new__
  5. The function obtained in the last step (that is, object.__new__ ) is called with the cls argument, where cls is probably CarModel ,最后是 CarModel 类的新实例。

我希望这是完全可以理解的。

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

原文由 Dolda2000 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题