使用类的__new__方法作为工厂:__init__被调用两次

使用类的__new__方法作为工厂:__init__被调用两次,第1张

使用类的__new__方法作为工厂:__init__被调用两次

当构造一个对象时,Python会调用其

__new__
方法来创建该对象,然后
__init__
在返回的对象上进行调用。当您
__new__
通过调用从内部创建对象时
Triangle()
,将导致对
__new__
和的进一步调用
__init__

您应该做的是:

class Shape(object):    def __new__(cls, desc):        if cls is Shape: if desc == 'big':   return super(Shape, cls).__new__(Rectangle) if desc == 'small': return super(Shape, cls).__new__(Triangle)        else: return super(Shape, cls).__new__(cls, desc)

它会创建一个

Rectangle
Triangle
不触发调用
__init__
,然后
__init__
仅被调用一次。

编辑以回答@Adrian关于super如何工作的问题:

super(Shape,cls)
搜索
cls.__mro__
以查找
Shape
,然后向下搜索序列的其余部分以找到属性。

Triangle.__mro__
(Triangle, Shape, object)

Rectangle.__mro__
(Rectangle, Shape, object)
Shape.__mro__
而是正义
(Shape,object)
。对于任何一种情况,当您调用
super(Shape,cls)
它时,它都会忽略mro序列中的所有内容,
Shape
因此只剩下单个元素元组
(object,)
,它用于查找所需的属性。

如果您拥有钻石继承关系,这将变得更加复杂:

class A(object): passclass B(A): passclass C(A): passclass D(B,C): pass

现在B中的方法可能会使用

super(B, cls)
,如果是B的实例会搜索,
(A,object)
但是如果你有一个
D
实例,相同的调用
B
将搜索,
(C, A, object)
因为
D.__mro__
is是
(B, C, A,object)

因此,在这种特殊情况下,您可以定义一个新的mixin类,该类可以修改形状的构造行为,并且可以具有从现有的三角形和矩形继承但构造不同的专用三角形和矩形。



欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5645220.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存