从屈服生成器函数中导出重复代码

时间:2018-03-05 15:33:19

标签: python generator

请注意以下方法:

def _locate(self, text):
        """
        This method accesses preceding locators if these exist, it then calls an overridable helper method called _relocate
        which receives text with readjusted boundaries and searches inside, the basic implemented behaviour is that of a logical or
        """
        if not self.precedents:
            for sub_segment in self._relocate(text, Segment(0, len(text), 1)):
                if self._multiple:
                    yield sub_segment
                elif self.max_segment.prob > self._prob_threshold:
                    yield self.max_segment
                    return
        else:
            for precedent in self.precedents:
                for segment in precedent.locate(text):
                    for sub_segment in self._relocate(text, segment):
                        if self._multiple:
                            yield sub_segment
                        elif self.max_segment.prob > self._prob_threshold:
                            yield self.max_segment
                            return

        # if we haven't found a good enough segment return the best one we came across while locating
        if not self._multiple:
            yield self.max_segment

它有一些重复的代码两次:

for sub_segment in self._relocate(text, segment):
    if self._multiple:
        yield sub_segment
    elif self.max_segment.prob > self._prob_threshold:
        yield self.max_segment
        return

我天真地以为我可能会定义一个单独的帮助器方法并且只需要一次代码就可以开始实现它,然而,事实证明这几乎是不可能的(因为代码同时使用了yield和return)并且导致了我在代码长度和运行时方面更加痛苦。

不确定我究竟在问什么(如果有什么我可能会问是否有人知道一些共享生成器代码的一般方法,或者看看如何在这里完成?),但无论如何作为发电机的话题,我发现这个经历非常有说服力,所以我想我会分享。

1 个答案:

答案 0 :(得分:1)

我认为你可以通过定义循环外部段的生成器来删除代码重复

def _locate(self, text):
        """
        This method accesses preceding locators if these exist, it then calls an overridable helper method called _relocate
        which receives text with readjusted boundaries and searches inside, the basic implemented behaviour is that of a logical or
        """
        if self.precedents:
            segments = (seg for precedent in self.precedents for seg in precedent.locate(text))
        else:
            segments = (Segment(0, len(text), 1),)

        for segment in segments:
            for sub_segment in self._relocate(text, segment):
                if self._multiple:
                    yield sub_segment
                elif self.max_segment.prob > self._prob_threshold:
                    yield self.max_segment
                    return

        # if we haven't found a good enough segment return the best one we came across while trying
        if not self._multiple:
            yield self.max_segment