2 回答

TA贡献1811条经验 获得超6个赞
使用factory method方法怎么样?当应该动态定义确切的实例类型时,这是一个不错的选择。好像:
class Monomial(Function):
@staticmethod
def create(coef: int, power: int, inner=Identity()):
if power == 0:
return Constant(coef)
else:
return Monomial(coef, power)
x = Monomial.create(...)

TA贡献1847条经验 获得超7个赞
调用类时返回不同类类型的__new__方法是覆盖方法而不是__init__. 返回的值__new__是用作实例的值(与__init__它甚至不允许返回值不同)。您已经正确开始,但是在内部尝试__new__通过调用它来实例化一个子类,只会重新输入Monomial.__new__- 您可能会在那里遇到递归错误。
因此,即使 Python 确实允许更改 的返回类型__new__,也许您应该考虑拥有一个工厂函数的想法 - 独立于任何类 - 它将返回正确类的实例。有时“越简单越好”。
无论如何,工厂方法的代码是:
class Monomial(Function):
def __init__(self, coef: int, power: int, inner=Identity()):
super().__init__(inner)
self.pow = power
self.coef = coef
class Constant(Monomial):
def __init__(self, c: int):
super().__init__(self, coef=c, power=0)
...
def create_monomial(coef, power):
if power == 0:
return Constant(coef)
return Monomial(coef, power)
(create_monomial 也可以是静态或类方法,你会发现更好)
而且,如果您真的认为它会更好,那么解开该__new__方法的一种方法是:
class Monomial(Function):
def __new__(cls, coef: int, power: int = 0, inner=Identity()):
if power == 0:
cls = Constant
return super().__new__(cls)
class Constant(Monomial):
def __init__(self, c: int, **kw):
super().__init__(c, 0)
Python 的实例化机制将调用__init__如果返回__new__的实例是self- 因此 Monomial 和 Constant__init__都将被正确调用。你只需要修复 Constant's__init__不要破坏power = 0它会得到的 ocasional参数。
修复签名将在那里花费更多的工作,并且可能涉及使用元类来实际吞咽,在其__call__方法中未使用powerConstant 的__init__;
另请注意,此处的“真正修复”是调用super().__new__需要显式传递类 - 与super()Python 提供的“self”或“cls”的其他用法不同。这是因为__new__它实际上是一个静态方法——Pythoncls在构建类时向其中添加了,但是通过“classmethods”使用的其他机制。
添加回答
举报