Python调用超级构造函数 - 我做得对吗?

时间:2014-08-03 10:36:47

标签: python coding-style dry

我有一个像这样的基类:

class Token:
    def __init__(self, value):
        self.value = value.strip()
        self.tokens = None

    def get_value(self):
        return self.value

    def tokenize(self):
        pass # abstract stub

    def __str__(self):
        return type(self).__name__ + ': '+ re.sub(r'\s+', ' ', self.value)

还有很多孩子的课程:

class T_DefineDirective(Token):
    def __init__(self, value):
        super().__init__(value)


class T_IncludeDirective(Token):
    def __init__(self, value):
        super().__init__(value)


class T_IfdefDirective(Token):
    def __init__(self, value):
        super().__init__(value)


class T_Identifier(Token):
    def __init__(self, value):
        super().__init__(value)


class T_Rvalue(Token):
    def __init__(self, value):
        super().__init__(value)

    def tokenize(self):
        pass # stuff here

现在我是一名干性程序员。我讨厌重复。如果您查看代码,__init__部分将被复制粘贴到所有子类中。

我的问题是,有没有办法避免重复,或者这是否真的是正确的方法?

(请注意,示例有点缩短,因此可能没有多大意义。但您可以看到我的意思)。

2 个答案:

答案 0 :(得分:2)

如果您在Token子类中没有任何其他设置工作要做,则可以安全地不覆盖__init__

如果你必须执行一些特定于子类的初始化,那么你正在使用的模式很好并且是“pythonic”#。


澄清:

  • 如果没有在类上定义__init__,那么Python将使用在其父类(其中一个)上定义的__init__方法,如果可能的话
    • 这是因为没有任何特殊规则可以覆盖魔法'像__init__
    • 这样的方法
  • 即使使用父类的初始化,也会创建子类的实例
    • 这是因为实际创作发生在__new__;然后将新创建的对象传递给__init__进行初始化

答案 1 :(得分:1)

如果你真的想要消除尽可能多的样板:

首先,如果所有内容都是__init__,则您不需要super();正如sapi的回答所解释的那样,特殊方法就像任何其他方法一样被继承。

其次,您可以动态创建一堆类:

token_classes = {
    'T_{}'.format(name): type('T_{}'.format(name), (Token,), {})
    for name in 'DefineDirective IncludeDirective IfdefDirective Identifier'.split()
}

你可以直接在dict中使用它们,但是如果你真的想把它们变成全局变量你可以:

globals().update(token_classes)

然而,避免重复的整个目标是使您的代码更具可读性和可维护性,在这种情况下,我认为我们正在实现相反的目标。 :)