3
\$\begingroup\$

In the bit of code below:

  1. How can I make add_day, add_ week and add_month work as a single function? They are almost copy-paste of one another. I'm trying to follow the DRY rule.
  2. How can I set this so that I don't use the variables day/week/cur_day?
import datetime
from collections import defaultdict
class ParsedData:
 def __init__(self, date, score, status, item_name):
 year, month, self.day = date.split("-")
 self.month = datetime.date(int(year), int(month), int(self.day)).strftime("%B")
 self.score = int(score)
 self.status = status
 self.item_name = item_name
class Log:
 def __init__(self):
 self.day = {}
 self.week = {}
 self.month = {}
 self.counter = {}
 self.default_data 
 def add_day(self, day, status, item_name, score):
 day = 'Day %i' % day
 if day not in self.day:
 self.day[day] = {"Comp": defaultdict(int),
 "Miss": defaultdict(int),
 "Post": defaultdict(int),
 "Add": defaultdict(int),
 "Score": 0}
 self.day[day][status][item_name] += 1
 self.day[day]['Score'] = score
 def add_week(self, week, status, item_name, score):
 week = 'Week %i' % week
 if week not in self.week:
 self.week[week] = {"Comp": defaultdict(int),
 "Miss": defaultdict(int),
 "Post": defaultdict(int),
 "Add": defaultdict(int),
 "Score": 0}
 self.week[week][status][item_name] += 1
 self.week[week]['Score'] = score
 def add_month(self, month, status, item_name, score):
 if month not in self.month:
 self.month[month] = {"Comp": defaultdict(int),
 "Miss": defaultdict(int),
 "Post": defaultdict(int),
 "Add": defaultdict(int),
 "Score": 0}
 self.month[month][status][item_name] += 1
 self.month[month]['Score'] = score
def update_views(log_file):
 log = Log()
 day = 0
 cur_day = None
 week = 1
 for line in log_file:
 parsed = ParsedData(*line.strip().split(","))
 if cur_day != parsed.day:
 cur_day = parsed.day
 day += 1
 if day % 7 == 0:
 week += 1
 log.add_day(day, parsed.status, parsed.item_name, parsed.score)
 log.add_week(week, parsed.status, parsed.item_name, parsed.score)
 log.add_month(parsed.month, parsed.status, parsed.item_name, parsed.score)
log_file = """2015-01-1,0,Add,DW_05
 2015年01月2日,-1,Post,CR_02
 2015年01月3日,-1,Comp,DIY_01
 2015年01月3日,-1,Post,CD_01
 2015年01月4日,-1,Miss,D_03
 2015年01月4日,0,Miss,D_03
 2015年01月4日,-1,Miss,CD_01
 2015年01月4日,0,Miss,LS_04
 2015年01月5日,1,Comp,DW_05
 2015年01月6日,1,Comp,ANI_06
 2015年01月6日,1,Comp,LS_04
 2015年01月7日,1,Comp,NMW_07
 2015年01月7日,1,Post,DW_05
 2015年01月7日,1,Miss,LP_08
 2015年01月8日,2,Post,CR_02
 2015年01月8日,2,Miss,SEV_09
 2015年01月10日,3,Comp,M_10
 2015年01月10日,3,Add,NID_11
 2015年01月11日,2,Add,ANI_06
 2015年01月12日,1,Add,VF_12
 2015年01月12日,0,Miss,DIY_01
 2015年01月12日,1,Add,NID_11
 2015年01月12日,0,Miss,D_03
 2015年01月13日,1,Miss,SEV_09
 2015年01月13日,2,Add,DW_05
 2015年01月13日,1,Comp,NMW_07
 2015年01月13日,1,Add,CPC_12""".splitlines()
update_views(log_file)
asked Jan 17, 2015 at 17:25
\$\endgroup\$
4
  • \$\begingroup\$ Have you actually tested this? All days, weeks and months share the same data... so what's the point of separating it? \$\endgroup\$ Commented Jan 17, 2015 at 20:28
  • \$\begingroup\$ It's for display purpose, the log goes to a MVC with three different display modes, daily, weekly and monthly. Each day will have a entry in the Day View, but the will be joined together in the week (every 7 days), and this will also be joined together in the month display. \$\endgroup\$ Commented Jan 17, 2015 at 23:20
  • \$\begingroup\$ I'm not sure you get it; self.month['January'] is self.month['February'] is self.day['Day 2']... and so on. Why? \$\endgroup\$ Commented Jan 17, 2015 at 23:45
  • \$\begingroup\$ Oh I see, somehow after refactoring I forgot to use deepcopy to set the default_data. \$\endgroup\$ Commented Jan 18, 2015 at 2:28

1 Answer 1

4
\$\begingroup\$

To avoid repetitive code, make the Log class do only one of the three things it currently does, and create three instances instead:

class Log(object):
 def __init__(self, name):
 self.name = name
 self.data = {}
 def add_item(self, key, status, item_name, score):
 key = '%s %i' % (self.name, key)
 if key not in self.data:
 self.data[key] = {"Comp": defaultdict(int),
 "Miss": defaultdict(int),
 "Post": defaultdict(int),
 "Add": defaultdict(int),
 "Score": 0}
 self.data[key][status][item_name] += 1
 self.data[key]['Score'] = score
def update_views(log_file):
 daily_log = Log('Day')
 weekly_log = Log('Week')
 monthly_log = Log('Month')
 ...
answered Jan 18, 2015 at 10:57
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.