我上课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__
。]
答案 0 :(得分: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)
答案 1 :(得分:1)
Alexey的答案(我的+1)的替代方法是传递base_arg1
参数中的基础对象并检查是否误用来传递基础对象(如果它是基类的实例)。其他agrument在技术上可以是可选的(比如None
),并在代码中决定时明确检查。
不同之处在于只有参数类型决定了使用两种可能的创建方式。如果无法在源代码中显式捕获对象的创建,则这是必要的(例如,某些结构包含参数元组的混合,其中一些具有初始值,其中一些具有对现有对象的引用。然后您将可能需要将参数作为关键字参数传递:
d = Derived(b, derived_arg1=derived_arg1, derived_arg2=derived_arg2)
更新:为了与初始类共享内部结构,可以使用这两种方法。但是,您必须意识到,如果其中一个对象试图修改共享数据,通常会发生有趣的事情。
答案 2 :(得分: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