max*_*max 2 python design-patterns class
我有一个类层次结构,__init__在其中class Base执行一些预初始化然后调用方法calculate.该calculate方法已定义class Base,但预计将在派生类中重新定义.重新定义calculate将使用仅在class Derived以下情况下可用的一些属性:
class Base:
def __init__(self, args):
# perform some pre-initialization
...
# now call method "calculate"
self.calculate()
class Derived(Base):
def __init__(self, args, additional_attr):
super().__init__(args)
# do some work and create new instance attributes
...
self.additional_attr = additional_attr
Run Code Online (Sandbox Code Playgroud)
这不起作用,因为calculate在class Derived分配self.additional_attr之前将调用方法in .
我无法将super().__init__(args)调用移到__init__方法的末尾,因为它所做的一些工作必须在处理之前完成additional_attr.
该怎么办?
也许你不应该calculate()在你的构造函数中进行调用.如果你不能通过允许基础构造函数首先完成来构造派生对象,那么你必须做错了恕我直言.一种明智的方法是将该调用移出构造函数,并可能创建一个工厂方法来自动进行调用.如果需要预先计算的实例,请使用该方法.
class Base(object):
def __init__(self, args):
# perform some initialization
pass
def calculate(self):
# do stuff
pass
@classmethod
def precalculated(cls, args):
# construct first
newBase = cls(args)
# now call method "calculate"
newBase.calculate()
return newBase
class Derived(Base):
def __init__(self, args, additional_attr):
super(Derived, self).__init__(args)
# do some work and create new instance attributes
self.additional_attr = additional_attr
@classmethod
def precalculated(cls, args, additional_attr): # also if you want
newDerived = cls(args, additional_attr)
newDerived.calculate()
return newDerived
newBase = Base('foo')
precalculatedBase = Base.precalculated('foo')
newDerived = Derived('foo', 'bar')
precalculatedDerived = Derived.precalculated('foo', 'bar')
Run Code Online (Sandbox Code Playgroud)
恕我直言,这是一个糟糕的设计,而且你正在混淆 Python 的对象系统。考虑一下在其他面向对象语言(如 C++)中,您甚至无法控制基类的创建。派生类的构造函数在代码运行之前调用基构造函数。这种行为几乎总是表现良好的类层次结构所期望的,改变它只会导致问题。
当然,您可以进行一些修补(例如self.additional_attr在调用super的构造函数之前进行分配,或其他技巧),但更好的方法是更改您的设计,以便不需要此类修改。由于您在这里提供了一个抽象的示例,因此很难提供更全面的设计建议。