9.3. Iterator¶
EN: Iterator
PL: Iterator
Type: object
9.3.1. Pattern¶
History (like browser history)

9.3.2. Problem¶

from dataclasses import dataclass, field
@dataclass
class BrowseHistory:
urls: list[str] = field(default_factory=list)
def push(self, url: str) -> None:
self.urls.append(url)
def pop(self) -> str:
self.urls.pop()
def get_urls(self) -> list[str]:
return self.urls
if __name__ == '__main__':
history = BrowseHistory()
history.push(url='https://a.example.com')
history.push(url='https://b.example.com')
history.push(url='https://c.example.com')
for i in range(len(history.get_urls())):
url = history.get_urls()[i]
print(i)
9.3.3. Solution¶

from dataclasses import dataclass, field
class Iterator:
def has_next(self) -> bool:
raise NotImplementedError
def current(self) -> str:
raise NotImplementedError
def next(self) -> None:
raise NotImplementedError
@dataclass
class BrowseHistory:
urls: list[str] = field(default_factory=list)
def push(self, url: str) -> None:
self.urls.append(url)
def pop(self) -> str:
self.urls.pop()
def get_urls(self) -> list[str]:
return self.urls
def create_iterator(self) -> Iterator:
return self.ListIterator(self)
@dataclass
class ListIterator(Iterator):
history: 'BrowseHistory'
index: int = 0
def has_next(self) -> bool:
return self.index < len(history.urls)
def current(self) -> str:
return history.urls[self.index]
def next(self) -> None:
self.index += 1
if __name__ == '__main__':
history = BrowseHistory()
history.push(url='https://a.example.com')
history.push(url='https://b.example.com')
history.push(url='https://c.example.com')
iterator = history.create_iterator()
while iterator.has_next():
url = iterator.current()
print(url)
iterator.next()
# https://a.example.com
# https://b.example.com
# https://c.example.com
9.3.4. Use Case - 0x01¶
from dataclasses import dataclass, field
@dataclass
class Browser:
history: list[str] = field(default_factory=list)
def open(self, url: str) -> None:
...
self.history.append(url)
def __iter__(self) -> 'Browser':
self._current = 0
return self
def __next__(self) -> str:
if self._current >= len(self.history):
raise StopIteration
result = self.history[self._current]
self._current += 1
return result
if __name__ == '__main__':
browser = Browser()
browser.open('https://python.astrotech.io')
browser.open('https://numpy.astrotech.io')
browser.open('https://pandas.astrotech.io')
browser.open('https://design-patterns.astrotech.io')
for url in browser:
print(url)
# https://python.astrotech.io
# https://numpy.astrotech.io
# https://pandas.astrotech.io
# https://design-patterns.astrotech.io
9.3.5. Use Case - 0x02¶
from dataclasses import dataclass, field
@dataclass
class Browser:
history: list[str] = field(default_factory=list)
def open(self, url: str) -> None:
...
self.history.append(url)
if __name__ == '__main__':
browser = Browser()
browser.open('https://python.astrotech.io')
browser.open('https://numpy.astrotech.io')
browser.open('https://pandas.astrotech.io')
browser.open('https://design-patterns.astrotech.io')
for url in browser.history:
print(url)
# https://python.astrotech.io
# https://numpy.astrotech.io
# https://pandas.astrotech.io
# https://design-patterns.astrotech.io
9.3.6. Assignments¶
"""
* Assignment: DesignPatterns Behavioral Iterator
* Complexity: easy
* Lines of code: 9 lines
* Time: 8 min
English:
1. Implement Iterator pattern
2. Run doctests - all must succeed
Polish:
1. Zaimplementuj wzorzec Iterator
2. Uruchom doctesty - wszystkie muszą się powieść
Tests:
>>> crew = Crew()
>>> crew += 'Mark Watney'
>>> crew += 'Jose Jimenez'
>>> crew += 'Melissa Lewis'
>>>
>>> for member in crew:
... print(member)
Mark Watney
Jose Jimenez
Melissa Lewis
"""
class Crew:
def __init__(self):
self.members = list()
def __iadd__(self, other):
self.members.append(other)
return self