我发现自己处于菱形继承的奇怪情况,更糟糕的是菱形中间的类共享一个成员。下面我展示了一段精简的代码,突出了我的问题。
我在编写类时使用的方法是从http://rhettinger.wordpress.com/2011/05/26/super-considered-super/中学到的,它链接在 python 文档站点上,用于内置函数super
class A(object):
pass
class B(A):
def __init__(self, z=None, **kwargs):
self.z = z
super(B, self).__init__(**kwargs)
# super(B, self).__init__(z=z, **kwargs)
class C(A):
def __init__(self, z=None, **kwargs):
self.z = z
super(C, self).__init__(**kwargs)
class D(B, C):
pass
d = D(z='y')
for arg, value in d.__dict__.iteritems():
print arg, ':', value
给出输出
z : None
问题是使用关键字参数来确保函数签名匹配的方法从类 C 的 init 调用中删除了 z 参数。我可以强制将参数添加回 kwargs(请参阅注释代码),但这会导致我无法实例化 B 类型的对象,因为这将导致调用不带参数的对象的 init,这是一个不错的功能,因为它可以防止我在实例化以下任何对象时输入无效参数。
我还注意到,如果我在设置变量之前有 super 行,那么问题就解决了,因为最高级别的对象将覆盖较低的级别。然而,我的代码大量构建在最后,因为所有实际的“设置”都是由低级类执行的,而更高级别的类将值传递到继承链中。是否有关于在哪里适合家长电话的指南?
任何想法Stackoverflow?
谢谢
ps 这只是“合作课程”的糟糕设计吗?究竟什么是合作课程?是否有应该遵循的规则或指导方针?
编辑:
Stackoverflow 不会让我回答我自己的问题,但我想出了一个解决方案。
我认为合作班级之间不应该有任何共享成员。如果有两个彼此独立的类(在某种意义上没有“是一种”关系)共享一个成员,那么您应该在继承关系中添加一个抽象级别。
共享成员应该被取出并放入一个单独的类中,该类继承自共享基类,并由菱形中的类继承。
以下是更正后的代码。为了与 OP 中的链接保持一致,我引入了一个 Root 基类
我应该指出我没有接受过正式的编程教育(就像我猜的大多数人一样),所以如果我使用了错误的术语,我深表歉意。
class Root(object):
pass
class A(Root):
pass
class HasAZ(Root):
def __init__(self, z=None, **kwargs):
self.z = z
super(HasAZ, self).__init__(**kwargs)
class B(HasAZ, A):
pass
class C(HasAZ, A):
pass
class D(B, C):
pass
d = D(z='y')
for arg, value in d.__dict__.iteritems():
print arg, ':', value