Python: OOP design for event pricing updates This was an interview question, I was supposed to refactor the EventPricingUpdate class to reduce the amount of nested ifs.
Here are the basic rules:


EventPricingUpdate() is responsible for updating the price of a list of events after each day.
Each event's price will be reduced by 10 for each day.
The price of each event must be in the range of 50 &lt;= price &lt;= 500.
The field days_from_start represents how many days before the event begins. If days_from_start &lt; 7, then the effect of pricing change will be doubled. For example, a regular event's price will be reduced by 10 * 2 each day in the last 6 days.
There are special event_types that behavors differently.


"music" events' price will always go up by 10 each day, and up by 10 * 2 each day in the last 6 days.
"construction" events' price will never change.
"sports" events' price will drop by double the regular amount(20 instead of 10).

The class should support easily adding new conditions for a new event_type.


As you can see below, I had trouble refactoring the nested ifs in the update() method, what are some good approach to refactor it?

class Event(object):
    def __init__(self, price, days_from_start, event_type):
        self.price = price
        self.days_from_start = days_from_start
        self.event_type = event_type

class EventPricingUpdate(object):
    def __init__(self, events):
        self.events = events

    def update(self):
      for event in self.events:
        if event.event_type == 'construction':
          continue
        elif event.event_type == 'music':
          if event.days_from_start &lt; 7 and event.price &lt;= 480:
            event.price += 20
          elif event.price &lt;= 490:
            event.price += 10
        elif event.event_type == 'sports':
          if event.days_from_start &lt; 7 and event.price &gt;= 90:
            event.price -= 40
          elif event.price &gt;= 70:
            event.price -= 20
        elif event.days_from_start &lt; 7 and event.price &gt;= 70:
            event.price -= 20
          elif event.price &gt;= 60:
            event.price -= 10
        event.days_from_start -= 1
      return self.events
After a small check, it seems the best solution is to add a condition per type of event, where you adjust accordingly.

Since all events have their effect 'doubled' on the last 7 days, you can use a single if for it

Lastly, you use a single if as well to check if you can update the event, regarding final price

Also I added a list comprehension to avoid looping through 'construction' events, whose value never changes

class EventPricingUpdate(object):
    ORIGINAL_REDUCTION = 10

    def __init__(self, events):
        self.events = events

    def events_to_update(self):
        return [event for event in self.events if event.event_type != 'construction']

    def update(self):
        for event in self.events_to_update():
            reduction = self.ORIGINAL_REDUCTION

            if event.event_type == 'music':
                reduction = reduction * -1

            if event.event_type == 'sports':
                reduction = reduction * 2

            if event.days_from_start &lt; 7:
                reduction = reduction * 2

            # if you use python 2 this if needs a slight change
            if 500 &gt;= event.price - reduction &gt;= 50:
                event.price -= reduction

            event.days_from_start -= 1

        return self.events


# Fill some events
events = [
    Event(event_type='construction', days_from_start=10, price=100),
    Event(event_type='music', days_from_start=10, price=100),
    Event(event_type='sports', days_from_start=10, price=100)
]

EventPricingUpdate(events).update()

# Check update
assert events[0].price == 100
assert events[1].price == 110
assert events[2].price == 80


As you can see, is easy to plug new events, just a new condition on the loop

If you want to go further on the refactoring, you will add the reduction on the list comprehension method