1

我有课Base。我想在一个类中扩展它的功能Derived。我本来打算写:

class Derived(Base):
  def __init__(self, base_arg1, base_arg2, derived_arg1, derived_arg2):
    super().__init__(base_arg1, base_arg2)
    # ...
  def derived_method1(self):
    # ...

有时我已经有一个Base实例,我想Derived基于它创建一个实例,即一个Derived共享Base对象的实例(不会从头开始重新创建它)。我想我可以写一个静态方法来做到这一点:

b = Base(arg1, arg2) # very large object, expensive to create or copy
d = Derived.from_base(b, derived_arg1, derived_arg2) # reuses existing b object

但这似乎是不可能的。要么我错过了使这项工作的方法,要么(更有可能)我错过了一个很大的原因,为什么它不能被允许工作。有人可以解释它是哪一个吗?

[当然,如果我使用组合而不是继承,这一切都很容易做到。但我希望避免所有通过的Base方法的委托。]Derived__getattr__

4

3 回答 3

2

依靠你的Base班级对base_arg1,所做的事情base_arg2

class Base(object):
    def __init__(self, base_arg1, base_arg2):
        self.base_arg1 = base_arg1
        self.base_arg2 = base_arg2
        ...

class Derived(Base):
    def __init__(self, base_arg1, base_arg2, derived_arg1, derived_arg2):
        super().__init__(base_arg1, base_arg2)
        ...

    @classmethod
    def from_base(cls, b, da1, da2):
        return cls(b.base_arg1, b.base_arg2, da1, da2)
于 2012-12-10T11:09:55.260 回答
1

Alexey 的答案(我的+1)的另一种方法是在 base_arg1参数中传递基对象并检查它是否被用于传递基对象(如果它是基类的实例)。另一个 agrument 在技术上可以是可选的(比如None),并在代码内部决定时明确检查。

不同之处在于只有参数类型决定使用两种可能的创建方式中的哪一种。如果对象的创建不能在源代码中显式捕获(例如,某些结构包含参数元组的混合,其中一些带有初始值,其中一些带有对现有对象的引用,则这是必要的。然后你会可能需要将参数作为关键字参数传递:

d = Derived(b, derived_arg1=derived_arg1, derived_arg2=derived_arg2)

更新:为了与初始类共享内部结构,可以使用两种方法。但是,您必须意识到一个事实,即如果其中一个对象试图修改共享数据,通常会发生一些有趣的事情。

于 2012-12-10T11:26:55.800 回答
1

在这里要清楚,我会用代码来回答。pepr 谈到了这个解决方案,但代码总是比英文更清晰。在这种情况下 Base 不应该是子类,但它应该是 Derived 的成员:

class Base(object):
    def __init__(self, base_arg1, base_arg2):
        self.base_arg1 = base_arg1
        self.base_arg2 = base_arg2

class Derived(object):
    def __init__(self, base, derived_arg1, derived_arg2):
        self.base = base
        self.derived_arg1 = derived_arg1
        self.derived_arg2 = derived_arg2

    def derived_method1(self):
        return self.base.base_arg1 * self.derived_arg1
于 2012-12-11T06:11:02.740 回答