注意:使用 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 许可协议
To begin with
super()
in itself is simply shorthand forsuper(A, B)
, whereA
is the class wherein the code occurs, andB
is the代码出现的函数的第一个参数;因此,在您的特定情况下,super().__new__(cls)
扩展为super(CarModel, cls).__new__(cls)
。反过来,
super(T, O)
返回一个“超级对象”。要了解超级对象的作用,您需要了解实例和类的属性引用在 Python 中是如何工作的。Assuming no
__getattr__
or__getattribute__
methods are involved, referencing attributeA
on an objectO
(that is, evaluatingO.A
或getattr(O, "A")
) 通过以下步骤进行:"A"
在O
的实例字典(O.__dict__
)中定义,则它直接返回该字典的值。O
的方法解析顺序中的每个类,在它们的每个字典中查找"A"
。如果找到,调用值D
。D
又没有定义__get__
,则按原样返回。但是,如果是这样,那么D
被称为“描述符”,并且它的__get__
方法被调用O
作为第一个参数,并且type(O)
作为---
作为第二个参数。类上的属性引用的工作方式大致相同,用类作为实例的引用,但有以下区别:
__get__
方法以None
作为第一个参数,被引用的类作为第二个参数。Python 使用描述符来实现诸如实例方法、类方法、静态方法和属性之类的东西。
使用
super(T, O)
创建的超级对象是一个(内置)对象,具有__getattribute__
方法,该方法在其上的每个属性引用上调用,并在O
的 MRO 中 T 之后的唯一类 的指令。然后它找到的值,它像往常一样调用__get__
on。这个过程有点复杂,所以作为一个例子,下面是它在你的具体案例中的工作方式。由于
CarModel
按原样定义,其 MRO 为[CarModel, object]
。super().__new__(cls)
扩展为super(CarModel, cls).__new__(cls)
,如上所述。super(CarModel, cls)
被评估为产生一个超级对象S
。"__new__"
S
(相当于在 Python 代码中调用getattr(S, "__new__")
)。S
was created on theCarModel
class, it considers the classes followingCarModel
in the MRO ofCarModel
, and finds"__new__"
在object
类本身的字典中。它的值是一个静态方法,有一个__get__
方法,它使用参数None
和cls
。由于__new__
是一个静态方法,它的__get__
方法只是按原样返回函数,未修改。因此,super(CarModel, cls).__new__
与object.__new__
。object.__new__
) is called with thecls
argument, wherecls
is probablyCarModel
,最后是CarModel
类的新实例。我希望这是完全可以理解的。
(为了完整起见,应该提到
object
类上的实际__new__
函数实际上不是静态方法,而是一个特殊的内置函数,它根本没有__get__
方法,但是因为__get__
静态方法上的方法只返回它们定义的函数,效果是一样的。)