Skip to content

Commit

Permalink
Add chapter_09 iterator pattern
Browse files Browse the repository at this point in the history
  • Loading branch information
balancy committed Oct 4, 2023
1 parent deaa3c0 commit d97f0e6
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 0 deletions.
1 change: 1 addition & 0 deletions patterns/chapter_09_iterator/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Init file for chapter_09_iterator package."""
24 changes: 24 additions & 0 deletions patterns/chapter_09_iterator/iterators.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"""Custom iterator class."""

from __future__ import annotations


class Iterator:
"""Iterator class."""

def __init__(self, collection: list[tuple[str, float]]) -> None:
"""Initialize iterator."""
self._collection = collection
self._index = 0

def __iter__(self) -> Iterator:
"""Return iterator."""
return self

def __next__(self) -> tuple[str, float]:
"""Return next element."""
if self._index >= len(self._collection):
raise StopIteration
current_element = self._collection[self._index]
self._index += 1
return current_element
25 changes: 25 additions & 0 deletions patterns/chapter_09_iterator/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"""Iterator module."""

from __future__ import annotations

from .menus import DinerMenu, Menu, PancackeMenu
from .waitress import Waitress


def run_pattern_example() -> None:
"""Run pattern example."""
pancake_menu: Menu = PancackeMenu()
diner_menu: Menu = DinerMenu()

pancake_menu.add_item({"pancake": 1.99})
pancake_menu.add_item({"waffle": 2.99})

diner_menu.add_item(("spaghetti", 3.99))
diner_menu.add_item(("meatballs", 4.99))

waitress: Waitress = Waitress([pancake_menu, diner_menu])
waitress.print_all_menus()


if __name__ == "__main__":
run_pattern_example()
74 changes: 74 additions & 0 deletions patterns/chapter_09_iterator/menus.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
"""Abstract Menu class and 2 implementations."""

from abc import ABC, abstractmethod

from .iterators import Iterator


class Menu(ABC):
"""Abstract Menu class."""

_description: str

@abstractmethod
def add_item(self, item) -> None:
"""Add item to menu (abstract method).
All child classes must implement this method.
"""
...

@abstractmethod
def create_iterator(self) -> Iterator:
"""Create iterator for menu items (abstract method).
All child classes must implement this method.
"""
...

@property
def description(self) -> str:
"""Return menu description."""
return self._description


class DinerMenu(Menu):
"""Diner menu class.
Uses tuples to store menu items.
"""

_description: str = 'Diner menu'

def __init__(self) -> None:
"""Initialize menu."""
self._menu_items: list[tuple[str, float]] = []

def add_item(self, item: tuple[str, float]) -> None:
"""Add item to menu."""
self._menu_items.append(item)

def create_iterator(self) -> Iterator:
"""Create iterator for menu items."""
return Iterator(self._menu_items)


class PancackeMenu(Menu):
"""Pancake menu class.
Uses dict to store menu items.
"""

_description = 'Pancake menu'

def __init__(self) -> None:
"""Initialize menu."""
self._menu_items: dict[str, float] = {}

def add_item(self, item: dict[str, float]) -> None:
"""Add item to menu."""
self._menu_items.update(item)

def create_iterator(self) -> Iterator:
"""Create iterator for menu items."""
return Iterator(list(self._menu_items.items()))
26 changes: 26 additions & 0 deletions patterns/chapter_09_iterator/waitress.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
"""Waitress class for printing menus."""

from typing import Iterable, cast

from .iterators import Iterator
from .menus import Menu


class Waitress:
"""Waitress class."""

def __init__(self, menus: Iterable[Menu]) -> None:
"""Initialize waitress with menus."""
self._menus = menus

def print_all_menus(self) -> None:
"""Print all menus."""
for menu in self._menus:
print(menu.description)
iterator = menu.create_iterator()
self._print_menu(iterator)

def _print_menu(self, iterator: Iterator) -> None:
"""Print one menu."""
for item, price, *_ in iterator:
print(f'- {cast(str, item)}: {price}')

0 comments on commit d97f0e6

Please sign in to comment.