python和sup中具有相同成员的类的菱形继承

2024-10-01 07:50:03 发布

您现在位置:Python中文网/ 问答频道 /正文

我发现自己处于钻石继承的奇怪境地,更糟糕的是钻石中间的类共享一个成员。下面我展示了一段代码,它突出了我的问题。在

我在编写我从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

产生输出

^{pr2}$

问题是,使用关键字参数来确保函数签名匹配的方法从类C的init调用中去掉了z参数。我可以强制地将参数添加回kwargs中(见注释代码),但这会导致我无法实例化类型为B的对象,因为这将导致对不带参数的object的init的调用,这是一个很好的特性,因为它可以防止我在实例化以下任何对象时输入无效的参数。在

我还注意到,如果在设置变量之前有一行super,那么问题就解决了,因为最高级别的对象将覆盖较低级别的对象。然而,我的代码主要是围绕着在末尾有超级代码而构建的,因为所有实际的“设置”都是由低级别的类执行的,而高级别的类则将值传递给继承链。是否有指导方针,以适应家长电话?在

有什么想法吗?在

谢谢

这是不是一个糟糕的“合作班”设计?什么是合作班?有没有应该遵循的规则或准则?在

编辑:

Stackoverflow不让我回答自己的问题,但我想出了一个解决方案。在

我认为合作班之间不应该有任何共享成员。如果有两个相互独立的类(在某种意义上没有“是一种”关系)共享一个成员,那么您应该在继承关系中添加一个抽象级别。在

共享成员应取出并放入一个单独的类中,该类继承自共享基类,并由菱形中的类继承。在

下面是正确的代码。为了与OP中的链接保持一致,我引入了一个根基类

我应该指出的是,我没有受过正规的编程教育(就像这里的大多数人一样),所以如果我使用了错误的术语,我很抱歉。在

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

Tags: 对象方法代码self参数objectinitvalue
2条回答

也许有更好的方法,但这应该避免重写:

class C(A):
    def __init__(self, z=None, **kwargs):
        if not hasattr(self, 'z'):
            self.z = z
        super(C, self).__init__(**kwargs)

Is this just a bad design of 'cooperative classes'?

是的,特别是因为属性冲突。如果属性的名称不相同,那么到目前为止,B.z不会被C.z覆盖。在

What is a cooperative class exactly?are there rules or guidelines one should follow?

你已经读过的那个:

http://rhettinger.wordpress.com/2011/05/26/super-considered-super/

据我所知,这是合作类规则/指南的最佳来源。在

你可以做出选择。您可以:

  • 使属性名在继承树中的所有类中唯一

或者

  • 总是把所有的论点都传下去。此时,您不妨将所有签名更改为__init__(self, **kwargs)

或者

  • 不要使用多重继承

相关问题 更多 >