Python重复代码删除

时间:2016-02-03 00:12:00

标签: python python-3.x refactoring

根据CodeClimate,下面简化类中的两个方法是质量大约为40的彼此重复。重构删除重复的最佳方法是什么?等效的字典理解具有非常小的质量,但在其他方面是相同的。

 class DataAdaptor:
     def __init__(self):
         self._feeds = {'field1': 'temperature', 'field2': 'humidity'}

     def parse_data(self, data):
         content = {}
         for field, feed in self._feeds.items():
             if feed in data:
                 content[field] = data[feed]
         return content

     def parse_content(self, content):
         data = {}
         for field, feed in self._feeds.items():
             if field in content:
                 data[feed] = content[field]
         return data

澄清:带字典理解的版本具有几乎完全相同的复制质量,但我认为它稍微不那么明确。

 class DataAdaptor:
     def __init__(self):
         self._feeds = {'field1': 'temperature', 'field2': 'humidity'}

     def parse_data(self, data):
         return {field: data[feed] for field, feed in self._feeds.items() if feed in data}

     def parse_content(self, content):
         return {feed: content[field] for field, feed in self._feeds.items() if field in content}

这是绿色字段开发,因此我们可以自由地做任何事情。

5 个答案:

答案 0 :(得分:3)

我已经阅读了前三个答案,我想提供一些不同的东西。不要重写这些功能。他们很好,因为他们是。它们简短易懂,易于阅读。为什么要搞砸他们?我从来没有使用CodeClimate而且不知道40的质量意味着什么,但我认为将任何静态代码检查工具视为关于如何编写软件的绝对最终权限是错误的。 。我打赌你要担心的是比一个简单的小函数中的部分重复更大的问题,正如你已经说过的那样可以写成单个字典理解。

但我有一个建议:将两个函数的名称更改为select_by_matching_valuesselect_by_matching_keys。这样可以了解他们的工作以及彼此之间的差异。

答案 1 :(得分:1)

我正在考虑的替代方案是存储反向查找字典。

 class DataAdaptor:
     def __init__(self):
         self._feeds = {'field1': 'temperature', 'field2': 'humidity'}
         self._fields = {'temperature': 'field1', 'humidity': 'field2'}

     def parse_data(self, data):
         return self._reform_data(data, self._fields)

     def parse_content(self, content):
         return self._reform_data(content, self._feeds)

     def _reform_data(self, data, names)
         return {names[k]: data[k] for k in names if k in data}

或者有更简单的方法来交换字典中的键和值吗?

答案 2 :(得分:0)

两者并不完全相同:它们以相反的方向复制参考文献。但是,编写简单的条件字典理解可能是最好的方法。更改输入参数以强调相似性:

parse_data(self, foo):
    return {field: foo[feed] for field, feed in self._feeds.iteritems() \
                                 if feed in foo}

... parse_content在检查和返回的内容方面略有不同。

parse_content(self, foo):
    return {feed: foo[field] for field, feed in self._feeds.iteritems() \
                                 if field in foo}

这有帮助吗?

答案 3 :(得分:0)

我看到的唯一方法是使用kwargs并将数据作为关键字传递,并使用基于此的逻辑:

class DataAdaptor:
    def __init__(self):
        self._feeds = {'field1': 'temperature', 'field2': 'humidity'}

    def parse_content(self, **kwargs):
        data, content = kwargs.get("data", {}), kwargs.get("content", {})
        return {k: data[v] for k, v in self._feeds.items() if v in data} if data\
            else {self._feeds[k]: content[k] for k in self._feeds.keys() & content}

您也可以使用self._feeds.keys() & data获取公共密钥,对于python2,您需要将其更改为self._feeds.viewkeys() & data

您也可以使用命名参数:

class DataAdaptor:
    def __init__(self):
        self._feeds = {'field1': 'temperature', 'field2': 'humidity'}

    def parse_content(self, data=None, content=None):
        return {k: data[v] for k, v in self._feeds.items() if v in data} if data\
            else {self._feeds[k]: content[k] for k in self._feeds.keys() & content}

虽然我个人更喜欢使用这两种方法。

答案 4 :(得分:0)

我们可以通过索引解决k和v,并在需要时神奇地反转索引,而不是将项目解压缩到k v对中

 def _parse_lol(self, source, num)
     result = {}
     for item in self._feeds.items():
         if item[1] in source:
             result[num] = source[1-num]
     return result

 def parse_data(self, data):
     return self.parse_lol(data, 0)

 def parse_content(self, content):
     return self.parse_lol(data, 1)

我可能会错位0和1,

UPD

 def parse_parse(self, **kwargs):
     direction = ["content", "data"].index(kwargs.keys()[0])
     source = kwargs.values()[0]
     result = {}
     for item in self._feeds.items():
         if item[1] in source:
             result[item[direction]] = source[item[1-direction]]
     return result