Python 删除重复代码

Python duplicate code removal

根据 CodeClimate,下面简化的 class 中的两种方法是彼此重复的,质量约为 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}

这是一个绿色领域开发,所以我们可以自由地做任何事情。

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

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}

这有帮助吗?

我看到的唯一方法是使用 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}

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

我们可以通过索引寻址 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

我已经阅读了前三个答案,我想提供一些不同的东西。不要重写这些函数。他们很好,因为他们是。它们简短、易于理解和阅读。为什么要惹他们?我从未使用过 CodeClimate,也不知道 40 的质量是什么意思,但我认为将任何静态代码检查工具视为应该如何编写软件的绝对最终权威是错误的。我打赌你有比简单的小函数中的部分重复更重要的事情要担心,正如你已经说过的,它可以写成一个单一的字典理解。

不过,我有一个建议:将这两个函数的名称更改为 select_by_matching_valuesselect_by_matching_keys 之类的名称。这样可以清楚地了解他们所做的事情以及他们之间的区别。

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

 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}

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