在类中重写函数的最紧凑和最简洁的方法是啥?

Posted

技术标签:

【中文标题】在类中重写函数的最紧凑和最简洁的方法是啥?【英文标题】:The most compact and neat way about overriding a function in a class?在类中重写函数的最紧凑和最简洁的方法是什么? 【发布时间】:2018-11-09 14:40:59 【问题描述】:

我正在尝试编写一个用于文本操作的类。这个想法是类将支持基本的文本预处理,但如果有人想编写一个非常复杂的预处理函数,他们应该能够使用基类并覆盖它。我尝试了以下方法,即使我可以以某种方式使其工作,但我认为这不是正确的方法。

class TextPreprocessor:
    def __init__(self, corpus):
        """Text Preprocessor base class.

            corpus: a list of sentences

        """
        self.corpus      = corpus
        self.word_tokens = [self.preprocess(sentence) for sentence in corpus]

    def preprocess(self,sentence):
        """
        strip each sentence , lowercase it and split by space # sentence.strip().lower().split()

        """

        return sentence.strip().lower().split()

    def preprocess_transform(self,sentence):

        return self.preprocess(sentence)

现在,如果我想编写一个新的预处理函数,这是最好的方法。我试过了,

class SubPreprocess(TextPreprocessor):
    def __init__(self, corpus):
        #### dummy preprocess function
        def preprocess(self, sentence):
            return sentence.strip().split() + ['HELLOOOOOOOOOOLLLL']
        super.__init__(corpus)

它不工作。我基本上想要的是预处理函数(修改后的),应该能够覆盖基类TextPreprocessor中的那个,这样当__init__被调用时,self.word_tokens,应该基于新的预处理函数

【问题讨论】:

你为什么要newting__init__中的函数? 【参考方案1】:

以下会做:

class SubPreprocess(TextPreprocessor):
    def preprocess(self, sentence):
        return sentence.strip().split() + ['HELLOOOOOOOOOOLLLL']

如果你现在调用SubPreprocess的构造函数,将会使用新的preprocess方法:

proc = SubPreprocess(some_corpus)  
# looks up any methods in the mro of SubPreprocess

【讨论】:

有意思,没想到这样做也继承了init函数 @Karl 否则,继承将毫无用处。您只需覆盖需要更改的方法。当这些被其他方法调用时,self.__class__ 的mro 确定查找顺序。 我做了同样的事情,但没有成功。但是,现在当我查看我的代码时,我意识到,在创建 SubPreprocess 类之后,我在不知不觉中调用了 TextPreprocessor 。这是最好的方法。谢谢。赞成。 :-) @Karl - 这是首选,因为对使用基类感兴趣但只想更改preprocess 函数的人应该远离额外的复杂性。就是这样。 @schwobaseggl,是的,这很清楚。不知何故,我从来没有想过这也适用于__init__。在我看到的几乎每个关于如何在 Python 中处理继承的示例中,子类总是有自己的构造函数,而超类是从那里显式调用的。很高兴在周五下午学习一些整洁的东西【参考方案2】:
class SubPreprocess(TextPreprocessor):
    def __init__(self, corpus):
        #this is how you initialise the superclass
        super(SubPreprocess, self).__init__(corpus)

    # the overridden function should be within the scope of the class, not under the initializer
    def preprocess(self, sentence):
        return sentence.strip().split() + ['HELLOOOOOOOOOOLLLL']

【讨论】:

【参考方案3】:

如果你想注入行为,只需使用一个函数:

class TheAlgorithm:
  def __init__(self, preprocess):
     self.preprocess = preprocess
  def process(self, corpus):
     after_a = self.part_a(corpus)
     preprocessed = self.preprocess(after_a)
     return self.part_b(preprocessed)

使用非常简单:

p = TheAlgorithm(lambda c: c.strip().split() + 'helllol')
p.process('the corpus')

实际上,如果你的类只是存储一些函数,你可以进行全功能编程:

def processor(preprocess):
   def algorithm(corpus):
      return part_b( preprocess(corpus) )

p = processor(lambda c: "-".join(c.split(",")))
assert "a-b-c" == p("a,b,c")

【讨论】:

【参考方案4】:

尝试更改:super.init(语料库) 到 super().init(语料库)

【讨论】:

以上是关于在类中重写函数的最紧凑和最简洁的方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

重写大型 IN 子句的最高效方法是啥?

添加和删​​除文件以不完全重写文件的最有效方法是啥?

请简述重载和重写的区别

重写和重载

java 重写 重载

方法的重载和重写