首页 > 解决方案 > Pythonic 减少子类的方法

问题描述

背景:所以,我正在研究一个 NLP 问题。我需要根据不同类型的文本文档提取不同类型的特征。我目前有一个设置,其中有一个 FeatureExtractor 基类,它根据不同类型的文档被多次子类化,所有这些都计算一组不同的特征并返回一个熊猫数据框作为输出。

所有这些子类都由一个名为 FeatureExtractionRunner 的包装类型类进一步调用,该类调用所有子类并计算所有文档的特征并返回所有类型文档的输出。

问题:这种计算特征的模式会导致很多子类。目前,我有 14 个子类,因为我有 14 种类型的文档。它可能会进一步扩展。而且要维护的课程太多了。有没有其他方法可以做到这一点?子类化较少

这是我解释的一些示例代表性代码:

from abc import ABCMeta, abstractmethod

class FeatureExtractor(metaclass=ABCMeta):
    #base feature extractor class
    def __init__(self, document):
        self.document = document
        
        
    @abstractmethod
    def doc_to_features(self):
        return NotImplemented
    
    
class ExtractorTypeA(FeatureExtractor):
    #do some feature calculations.....
    
    def _calculate_shape_features(self):
        return None
    
    def _calculate_size_features(self):
        return None
    
    def doc_to_features(self):
        #calls all the fancy feature calculation methods like 
        f1 = self._calculate_shape_features(self.document)
        f2 = self._calculate_size_features(self.document)
        #do some calculations on the document and return a pandas dataframe by merging them  (merge f1, f2....etc)
        data = "dataframe-1"
        return data
    
    
class ExtractorTypeB(FeatureExtractor):
    #do some feature calculations.....
    
    def _calculate_some_fancy_features(self):
        return None
    
    def _calculate_some_more_fancy_features(self):
        return None
    
    def doc_to_features(self):
        #calls all the fancy feature calculation methods
        f1 = self._calculate_some_fancy_features(self.document)
        f2 = self._calculate_some_more_fancy_features(self.document)
        #do some calculations on the document and return a pandas dataframe (merge f1, f2 etc)
        data = "dataframe-2"
        return data
    
class ExtractorTypeC(FeatureExtractor):
    #do some feature calculations.....
    
    def doc_to_features(self):
        #do some calculations on the document and return a pandas dataframe
        data = "dataframe-3"
        return data

class FeatureExtractionRunner:
    #a class to call all types of feature extractors 
    def __init__(self, document, *args, **kwargs):
        self.document = document
        self.type_a = ExtractorTypeA(self.document)
        self.type_b = ExtractorTypeB(self.document)
        self.type_c = ExtractorTypeC(self.document)
        #more of these extractors would be there
        
    def call_all_type_of_extractors(self):
        type_a_features = self.type_a.doc_to_features()
        type_b_features = self.type_b.doc_to_features()
        type_c_features = self.type_c.doc_to_features()
        #more such extractors would be there....
        
        return [type_a_features, type_b_features, type_c_features]
        
        
all_type_of_features = FeatureExtractionRunner("some document").call_all_type_of_extractors()

标签: python-3.xdesign-patternsnlppipelinecomposition

解决方案


__init__首先回答这个问题,您可能会以每次都编写方法为代价来完全避免子类化。或者您可以完全摆脱这些类并将它们转换为一堆函数。甚至您可以将所有课程加入一个课程。请注意,这些方法都不会使代码更简单或更易于维护,实际上它们只会在某种程度上改变它的形状。

恕我直言,这种情况是固有问题复杂性的一个完美例子,我的意思是域(NLP)和特定用例(文档特征提取)本身就是复杂的。

例如,featureXfeatureY可能是完全不同的东西,无法完全计算,因此您最终只能使用一种方法。同样,在数据框中合并这些特征的过程可能与合并花哨的特征的过程不同。在这种情况下拥有很多函数/类对我来说似乎是完全合理的,将它们分开也是合乎逻辑和可维护的明智之举。

也就是说,如果您可以将一些代码组合成一个更通用的函数,那么真正的代码减少可能feature calculation methods是可能的,但我不能确定它是否可能。


推荐阅读