多次执行的Python类方法

时间:2018-08-14 19:32:36

标签: python pandas oop subclass super

我是OOP和Python类继承的新手。我正在使用Pandas数据框,从“单元格”中提取信息,从找到它的单元格中删除信息,然后将保存的信息放入新列中。

我有四个类,每个类都从以下列表中的前一个继承。基础类Reader在数据帧中读取,Extractor使用RegEx查找与技术信息的匹配项,Categories包含针对给定类别返回的Extractor方法的信息, Looperiterrows()读取数据帧,确定给定行使用哪种Categories方法,并将Extractor的值分配给作为数据帧列返回的列表索引。

我遇到的问题是,我的Extractor方法被调用的次数超出了我希望的次数/超出了其应有的次数,这意味着在以后的每次调用中,给定方法找到技术的可能性由于删除操作,信息减少。我不知道这是否是因为使用self指向该方法的行为会调用它,或者如果我使用super()的方法不正确,或者我的代码中是否存在由于以下原因导致无法理解的冗余:我的经验有限。

我一直在阅读有关subclassing的信息,并且很好奇是否有人在此找到可行的解决方案,或者问题是否有更简单的解决方案。

下面是我的程序示例,其中包含打印语句及其输出。

class Reader(object):
    def __init__(self, dataframe):
        super(Reader, self).__init__()
        self.df = dataframe.replace({r'[^\x00-\x7F]+':''}, regex=True, 
        inplace = True) # Remove non-ascii characters
        self.df = dataframe.applymap(str) # Necessary for RegEx operations
        self.category = self.df.columns.get_loc('Category')
        self.Name = self.df.columns.get_loc('Name')
        self.Desc = self.df.columns.get_loc('Description')

class Extractor(Reader):
    def __init__(self):
        super(Extractor, self).__init__(dataframe)

        self.cellNames = []
        self.cellDesc = []
        for idx, cell in self.df.iterrows():
             self.cellNames.append(self.df.iat[index, self.Name])
             self.cellDesc.append(self.df.iat[index, self.Desc])

    def getDiameter(self, compilers, idx): # Compilers is a list of RegEx compilers
        diameterValue = None
        for compiler in compilers:
            matchList = [x.group() for x in re.finditer(compiler, self.cellNames[idx])]
            try:
                match = matchList[0] # finditer's first full match
            except IndexError:
                if compiler == compilers[-1]:
                    break
                else:
                    continue
            if len(matchlist) > 0: # I was getting empty matchLists running test cases
                self.cellNames[idx]  = cellNames[idx].replace(match, '')
                diameterValue = match
                print 1, diameterValue
                return diameterValue
        # If no match, do the same thing but for cellDesc
        # If no match, diameterValue still == None
        print 2, diameterValue
        return diameterValue


class Categories(Extractor):
    def __init__(self):
        super(Categories, self).__init__()

    def some_rules(self):
        print 3, self.getDiameter(compilers, idx)
        return self.getDiameter(compilers, idx)


class Looper(Categories):
    def __init__(self):
        super(Looper, self).__init__()

    def doLoop(self):
        diameterCol = # empty list the same size as a dataframe column
        global idx
        for idx, row in self.df.iterrows():
            if 'some category' in self.df.iat[idx, self.category]:
               print 4, self.some_rules()[0] # I think this is pointing to Extractor.getDiameter. I would like this to be the only pointer that invokes the method.
               diameterCol[idx] = some_rules()[0]
        self.df['Diameter'] = diameterCol
        return self.df

if __name__ == '__main__':
    dataframe = pd.read_excel(infileName, sheet_name = 'Sheet1')
    myData = Reader(dataframe)
    Looper().doLoop()

输出(一行):

3 diameterValue # Primary and preferred RegEx match
1 diameterValue2 # Secondary RegEx match, no more after this
2 None
3 None
2 None
4 None
2 None
3 None
2 None

1 个答案:

答案 0 :(得分:0)

通过修改Categories来解决,后者正在对Extractor方法进行冗余调用。相反,我直接用Looper中的参数来调用这些方法。