How is class Franchise, linked with Class Menu? in Below Python Code?

49 Views Asked by At

What informs the code that The relationship between the Franchise and Menu classes is that The Franchise class has an attribute menus that stores instances of the Menu class, when clearly Menu and menus are two different attributes?

I expected to have a line of code that actually connects class Menu and class Franchise

class Menu:
  def __init__(self, name, items, start_time, end_time):
    self.name = name
    self.items = items
    self.start_time = start_time
    self.end_time = end_time

  def __repr__(self):
    representative_string = "{name} available from {start_time} to {end_time}"
    return representative_string.format(name=self.name, start_time=self.start_time, end_time=self.end_time)

  def calculate_bill(self, purchased_items):
    total_price = 0
    for item in purchased_items:
      total_price += self.items[item]
    return total_price


brunch = Menu('brunch', {'pancakes': 7.50, 'waffles': 9.00, 'burger': 11.00, 'home fries': 4.50, 'coffee': 1.50, 'espresso': 3.00, 'tea': 1.00, 'mimosa': 10.50, 'orange juice': 3.50}, 11.00, 16.00)

early_bird = Menu('early_bird', {'salumeria plate': 8.00, 'salad and breadsticks(serves 2, no refills)': 14.00, 'pizza with quattro formaggi': 9.00, 'duck rugu': 17.50, 'mushroom ravioli (vegan)': 13.50, 'coffee': 1.50, 'espresso': 3.00}, 15.00, 18.00)

dinner = Menu('dinner', {'crostini with eggplant caponata': 13.00, 'caesar salad': 16.00, 'pizza with quattro formaggi': 11.00, 'duck ragu': 19.50, 'mushroom ravioli (vegan)': 13.50, 'coffee': 2.00, 'espresso': 3.00}, 17.00, 23.00)

kids = Menu('kids', {'chicken nuggets': 6.50, 'fusilli with wild mushrooms': 12.00, 'apple juice': 3.00}, 11.00, 21.00)

print(brunch)

breakfast_order = ['pancakes', 'home fries', 'coffee']
total_price = brunch.calculate_bill(breakfast_order)
print('Total price for breakfast:', total_price)

last_order = ['salumeria plate', 'mushroom ravioli (vegan)']
total_price = early_bird.calculate_bill(last_order)
print('Total price for last order:', total_price)


class Franchise():
  def __init__(self, address, menus):
    self.address = address
    self.menus = menus

  def __repr__(self):
    return f"{self.address}"

  def available_menus(self, time):
    available_orders = []
    for menu in self.menus:
      if (time >= menu.start_time and time <= menu.end_time):
        available_orders.append(menu.name)  
    return available_orders


flagship_store = Franchise("1232 West End Road", [brunch, early_bird, dinner, kids])

new_installment = Franchise("12 East Mulberry Street", [brunch, early_bird, dinner, kids])

available_menus = flagship_store.available_menus(12.00)
print('Available menus at 12.00 PM:', available_menus)
1

There are 1 best solutions below

0
On

In your code example the class definition has no direct link between the two classes. Implicitly menus of Franchise must be an iterable (e.g. a list) of objects that have start_time, end_time and name as attributes (in order to make "available_menus" work).

The variable menu that is created when iterating over self.menus could be renamed to any other name.

If you want it explicit you could modify your init function using typing.

from typing import List

class Franchise():
  def __init__(self, address: str, menus: List[Menu]):
    self.address = address
    self.menus = menus

Or even asserting the type:

class Franchise():
  def __init__(self, address, menus):
    self.address = address
    self.menus = menus
    assert all(isinstance(entry, Menu) for entry in self.menus)

Note that python uses the concept of Duck Typing https://en.wikipedia.org/wiki/Duck_typing so Franchise will work with every "menus" as long as the code can run. Asserting the class Menu would prevent that, while typing does not. It would even work with an empty list as menus (available_orders would be an empty list as well)