注意: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
问题1 super()
是什么意思?这是否意味着CarModel
的父类?
问题2我也很难理解函数__new__
是如何工作的?具体来说,下面这一行。
model = super().__new__(cls)
__new__
的说明:
The constructor function is called
__new__
as opposed to__init__
, and accepts exactly one argument, the class that is being constructed (it is called before the object is constructed, so there is no self argument). It also has to return the newly created object.
super()
用于引用超类(即从中进行子类化的父类)。__new__
是一个调用的方法,用于创建类的新实例(如果已定义)。以
super()
开始本身就是super(A, B)
的简写,其中A
是代码出现的类,而B
是代码出现的函数的第一个参数;因此在您的特定情况下,super().__new__(cls)
扩展到super(CarModel, cls).__new__(cls)
。反过来,
super(T, O)
返回一个“超级对象”。要了解超级对象的功能,您需要了解实例和类上的属性引用在Python中是如何工作的。假设不涉及
__getattr__
或__getattribute__
方法,则在对象O
(即,计算O.A
或getattr(O, "A")
)上引用属性A
将通过以下步骤进行:"A"
是在O
的实例dict(O.__dict__
)中定义的,则直接返回dict上的值,与实际值完全相同。O
方法解析顺序中的每个类,在它们的每个dict中查找"A"
。如果找到,调用值D
。D
没有定义__get__
,则返回原样。但是,如果它这样做了,那么D
被称为“描述符”,它的__get__
方法被调用,第一个参数是O
,第二个参数是type(O)
。类上的属性引用的工作原理大致相同,将引用的类替换为实例,但有以下区别:
__get__
方法时,第一个参数是None
,第二个参数是被引用的类。Python使用描述符实现实例方法、类方法、静态方法和属性等。
然后,使用
super(T, O)
创建的超级对象是一个(内置的)对象,其上的每个属性引用都调用了__getattribute__
方法,并在O
的MRO中的T后面的类的指令中查找该属性。然后它找到的值,像往常一样调用__get__
。这个过程有点复杂,因此作为一个例子,下面是它如何处理您的特定案例。因为
CarModel
是按原样定义的,所以它的MRO是[CarModel, object]
。super().__new__(cls)
展开为super(CarModel, cls).__new__(cls)
,如上所述。super(CarModel, cls)
被求值以产生一个超级对象S
。S
上获取属性"__new__"
(相当于在Python代码中调用getattr(S, "__new__")
)。S
是在CarModel
类上创建的,它考虑CarModel
的MRO中CarModel
之后的类,并在object
类本身的dict中找到"__new__"
。它的值是一个静态方法,它有一个__get__
方法,用参数None
和cls
调用。因为__new__
是一个静态方法,所以它的__get__
方法只返回未经修改的函数。因此,super(CarModel, cls).__new__
与object.__new__
完全相同。object.__new__
)中获得的函数用cls
参数调用,其中cls
可能是CarModel
,最后是CarModel
类的新实例。我希望这完全可以理解。
(为了完整起见,应该提到的是,
object
类上的实际__new__
函数实际上并不是静态方法,而是一个特殊的内置函数,它根本没有__get__
方法,但是由于静态方法上的__get__
方法只返回它们定义的函数,效果是一样的。)我相信,您使用的是Python3,其中不需要为super提供相同的类名。Super引用当前类的基类,并执行正确的Method Resolution Order以从正确的基类调用方法。
__new__
是调用以创建实例的方法。它是first step in the instance creation。相关问题 更多 >
编程相关推荐