-1

这是网络抓取项目中使用的 python 类内部的一个片段。我想遍历一个新抓取的数据字典,将其与每个级别的先前抓取的索引进行比较,并将需要更新的值添加到另一个深度嵌套的字典以供以后处理。我可以使用什么策略来清理它并仍然获得相同的结果?

self.new_stats[tour] = {}
parsed_stats = parse_stat_year(CURRENT_STAT_YEAR, self.scraped_stats_index[tour])

for pname, stats_by_year in parsed_stats.items():
  if pname in self.raw_players_with_stats[tour]:
    player = self.raw_players_with_stats[tour][pname]

    if 'stats' in player:
      for y, stats_by_cat in stats_by_year.items():
        if str(y) in player['stats']:
          for cat, stat in stats_by_cat.items():
            if cat in player['stats'][str(y)]:
              for prop, val in stat.items():
                if (not prop in player['stats'][str(y)][cat]) or (player['stats'][str(y)][cat][prop] != val):
                  self.new_stats[tour].setdefault(pname,{}).setdefault(y,{}).setdefault(cat,{})[prop] = val
            else:
              self.new_stats[tour].setdefault(pname,{}).setdefault(y,{})[cat] = stat
        else:
          self.new_stats[tour].setdefault(pname,{})[y] = stats_by_cat
    else:
      self.new_stats[tour][pname] = stats_by_year

  elif pname in self.new_player_urls[tour]:
    self.new_stats[tour][pname] = stats_by_year
4

1 回答 1

2

我将从单元测试开始,以确保在每次重构迭代之后我的代码仍然有效。

我会使用有意义的数据结构和方法,因此代码更具自我描述性。如果您不想推出单独的数据持有者类,有时您会发现namedtuple对此非常有用。

最后,我会将这个又大又丑if...for...else的块分解成有意义的更小的块,如下所示:

# instead of this original code...

for pname, stats_by_year in parsed_stats.items():
  if pname in self.raw_players_with_stats[tour]:
    #...
  elif pname in self.new_player_urls[tour]:
    self.new_stats[tour][pname] = stats_by_year

# you get something like this

for player_name, stats_by_year in parser_stats.iteritems():
  if self.has_raw_player(player_name):
    self.process_new_raw_player(player_name, stats_by_year)
  elif self.is_player_new(player_name):
     self.insert_new_stat_for_player( player_name, stats_by_year )

更容易阅读、测试和理解

而且,如果你有空闲时间,我会花时间阅读Robert Martin 的 Clean Code。它一定会得到回报的!

编辑

像这样清理冗长且难以阅读的单行

#...
self.new_stats[tour].setdefault(pname,{}).setdefault(y,{}).setdefault(cat,{})[prop] = val
#...

例如,它看起来像这样:

def insert_new_stat(self, tour, pname, y, cat, prop, val):
  player_stat = self.new_stats[tour].setdefault(pname, {})
  y_param = player_stat.setdefault(y, {}) # what is y??
  category_stats = ...
  prop_stats = ...
  ... = val

您的代码肯定会更加冗长和冗长,尽管显式优于隐式

于 2013-01-01T16:14:22.370 回答