2012-07-17 54 views
3

我有很多描述层次结构的Python类型,它们的属性越来越具体。而不是试图去描述它的话,这里有一个例子:如何在Python中没有is-a关系的情况下共享属性?

class A: 
    @property 
    def prop1(self): 
     return self._prop1 

class B: 
    @property 
    def prop1(self): 
     return self._prop1 

    @property 
    def prop2(self): 
     return self._prop2 

class C: 
    @property 
    def prop1(self): 
     return self._prop1 

    @property 
    def prop2(self): 
     return self._prop2 

    @property 
    def prop3(self): 
     return self._prop3 

因此,当你走在班级名单,B拥有所有的A的属性,然后一些额外的人的。 C具有B的所有属性,然后是一些额外的属性,依此类推。如果可能,我想尽量减少上述定义的重复。

一个明显的解决方案是使用继承,使BA的一个子类等等。但是,这些类型的语义不遵循is-a关系;我不想isinstance(bObject, A)True。在Python中是否有另一种方式直接允许这种不使用子类的属性共享?

+0

您可以使用组合而不是子类。 – TheZ 2012-07-17 16:08:44

+0

我想你的意思是我可以在每个'B'内部放置一个'A',然后重新实现''''''''''从''A''实例拉取属性访问器。这是我们想到的另一种解决方案,但这看起来不像上面所示的那样更紧凑。 – 2012-07-17 16:10:04

+0

为什么你真的关心'isinstance'返回什么?你真的有一个很好的理由来永远调用'isinstance'吗? – geoffspear 2012-07-17 16:13:54

回答

7

您可以使用一个装饰:

def has_prop1(cls): 
    @property 
    def prop1(self): 
     return self._prop1 

    cls.prop1 = prop1 

    return cls 

@has_prop1 
class A(object): 
    pass 

合成会是这样的:

@has_prop1 
@has_prop2 
class B(object): 
    pass 

甚至是这样的:

def has_many_properties(cls): 
    return has_prop1(has_prop2(has_prop3(cls))) 

@has_many_properties 
class C(object): 
    pass 
+0

非常好的解决方案。 – 2012-07-17 16:21:49

0

你说“我不想说谎,并说,如果C实际上没有,那么C就是A,这些类型的特征不符合子类的语义。“以你模糊的例子来说,目前还不清楚该走哪条路。

如果你说这是因为有一个在class A附加功能并不适用于class C,那么我会组成扯起了阶级的财产的一部分,所以你必须ABCAPropsBProps,和CProps分别给出了属性类的适当继承关系。

如果没有这样的附加功能,而这不仅仅是巧合的属性建立你带路,然后精神上重命名class Aclass ProvidesProp1,注意class C是-A提供prop1类,并接受class C因此是-a class A

相关问题