2014-01-31 13 views
0

我有两个班,一个共同的功能f,喜欢这里:两个班级,结构相同的方法,但一个不同的命名变量

class ClassA(object): 

    def f(self, var): 
     self.A = g(var, self.A) 

    # specific code for ClassA, also changing self.A 

class ClassB(object): 

    def f(self, var): 
     self.B = g(var, self.B) 

    # specific code for ClassB, also changing self.B 

在两个班,f做两个变量称为AB相同,这在结构上是等同的。我想把f它放到一个抽象类中以避免代码重复。要做到这一点的方法之一是

class ClassX(object): 

    def f(self, var): 
     self.X = g(var, self.X) 

class ClassA(ClassX): 

    # specific code for ClassA, also changing self.X 

class ClassB(ClassX): 

    # specific code for ClassB, also changing self.X 

在这个解决方案中的变量AB已更名X。然而,为了让我的代码更加自我解释,我想保留X这些特殊名称(如A,B)在特殊类中。

有没有办法做到这一点?

如果您可以建议更有意义的描述性标题,请对此留言,以便对社区更有价值。

编辑:该解决方案还应该工作,如果变量AB采取这样一种类型,是通过按值,应假定这两个自己的价值和类型可以从类的外部程序执行过程中被改变。

回答

2

首先,一个告诫:如果你的情况实际上需要你描述的那种继承,那么变量名应该是相同的。在大多数情况下,给两个相关类中相同的属性赋予不同的名称不会使代码更加自我解释 - 它使减少了自我解释。当它们真的相同时,它会使属性看起来不同,从而增加了复杂性和混淆的可能性。

但是,我可以想象出几种情况,你可能想要做这样的事情 - 这听起来有点像你想为两种不同类型的对象定义一个通用接口。一种简单的方法是使用属性来定义别名;所以在每个班级中,您都会拥有不同的属性(AB),但是您还需要定义一个属性,即X,在这两种情况下都可以访问相应的属性。所以在ClassA,你会做这样的事情在类定义:

@property 
def X(self): 
    return self.A 
@x.setter 
def X(self, value): 
    self.A = value 
@x.deleter 
def X(self): 
    del self.A 

而且在ClassB

@property 
def X(self): 
    return self.B 
@x.setter 
def X(self, value): 
    self.B = value 
@x.deleter 
def X(self): 
    del self.B 

然后,你可以定义一个共同的功能,将与X只有工作,这子类可以继承,以适当的方式覆盖属性X

这是很少值得追加层的间接,但。大多数情况下,如果两个类共享一个方法是有很好的理由的,那么他们也应该共享方法改变的属性,名称和全部。

+1

我想补充一点,如果你确实有一个不同的属性有不同的名字,但你想对它们执行相同的处理,你应该使用独立的函数来处理。并非所有事物都属于一类。 –

+0

谢谢,它有点多结构,但似乎使用'@ property'仍然是最简单的策略。但是,我已经改变了你的方法,并把它放到基类中,比如'@property def X(self):return self .__ getattribute __ [self.Xname]'并且分配一个属性'self.Xname',它是''A' '或''B'到初始化的具体类。这具有隐藏抽象基类中的结构并使代码简单的更具体派生类的优点。此外,如果我决定写另一个'ClassC',它将节省工作。 – flonk

+0

好吧,如果这样做可以节省你很多工作,那么我真的认为你所有的类都应该具有相同的属性名称。启发式地讲,这是一个强烈的信号,你没有抽象地想到你的课程。但没有看到具体的代码,我无法确定。另外,我鼓励你按照Silas Ray的建议使用'getattr',而不是'__geattribute__',这是为了覆盖,而不是使用(参见[这里](http://stackoverflow.com/questions/1944625/what- is-the-relationship-between-getattr-and-getattr)for more)。 – senderle

1

如果你想要做的只是一个实例属性,你可以使用property

class A(object): 

    def f(self, var): 
     self.x = g(var, self.x) 

    @property 
    def x(self): 

     return getattr(self, self.x_alias) 

    @x.setter 
    def x(self, val): 

     setattr(self, self.x_alias, val) 

class AA(A): 

    x_alias = 'aval' 

    def __init__(self, aval): 

     self.aval = aval 

class AB(A): 

    x_alias = 'bval' 

    def __init__(self, bval): 

     self.bval = bval 
相关问题