当构造一个对象时,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类,该类可以修改形状的构造行为,并且可以具有从现有的三角形和矩形继承但构造不同的专用三角形和矩形。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)