Last active
September 16, 2020 19:16
-
-
Save ethmcc/095fe476e33c82e218f13e605a6455ef to your computer and use it in GitHub Desktop.
Design Patterns in Python for the Untrained Eye
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Exercises from PyCon 2019 workshop | |
# https://www.youtube.com/watch?v=o1FZ_Bd4DSM | |
from abc import ABC, abstractmethod | |
# Template method design pattern | |
class AverageCalculator(ABC): | |
'''Design Patterns in Python Exercise B.''' | |
def average(self): | |
try: | |
num_items = 0 | |
total_sum = 0 | |
while self.has_next(): | |
total_sum += self.next_item() | |
num_items += 1 | |
if num_items == 0: | |
raise RuntimeError("Can't compute the average of zero items.") | |
return total_sum / num_items | |
finally: | |
self.dispose() | |
@abstractmethod | |
def has_next(self): | |
pass | |
@abstractmethod | |
def next_item(self): | |
pass | |
def dispose(self): | |
pass | |
# Exercise solution: | |
class MemoryAverageCalculator(AverageCalculator): | |
'''Exercise B solution.''' | |
def __init__(self, input_list): | |
self.memory = input_list | |
def has_next(self): | |
return not not self.memory | |
def next_item(self): | |
return self.memory.pop() | |
# Observer pattern | |
class Observable: | |
def __init__(self): | |
self.__observers = [] | |
def add_observer(self, observer): | |
self.__observers.append(observer) | |
def delete_observer(self, observer): | |
self.__observers.remove(observer) | |
def notify_observers(self, *args): | |
for observer in self.__observers: | |
observer.update(self, *args) | |
class Observer(ABC): | |
@abstractmethod | |
def update(self, observable, *args): | |
pass | |
# Exercise solution: | |
class Twitter(Observer, Observable): | |
'''Exercise D solution.''' | |
def __init__(self, name: str): | |
super().__init__() | |
self.name = name | |
self.tweets = list() | |
def follow(self, other): | |
other.add_observer(self) | |
return self | |
def tweet(self, twit): | |
self.tweets.append(twit) | |
self.notify_observers(twit) | |
def update(self, changed_account, new_tweet): | |
print(f'{self.name} received a tweet from {changed_account.name}: {new_tweet}') | |
if __name__ == "__main__": | |
# Template method pattern | |
mac = MemoryAverageCalculator([3, 1, 4, 1, 5, 9, 2, 6, 5, 3]) | |
print(mac.average()) | |
# Observer pattern | |
a = Twitter('Alice') | |
k = Twitter('King') | |
q = Twitter('Queen') | |
h = Twitter('Mad Hatter') | |
c = Twitter('Cheshire Cat') | |
a.follow(c).follow(h).follow(q) | |
k.follow(q) | |
q.follow(q).follow(h) | |
h.follow(a).follow(q).follow(c) | |
print(f'==== {q.name} tweets ====') | |
q.tweet('Off with their heads!') | |
print(f'\n==== {a.name} tweets ====') | |
a.tweet('What a strange world we live in.') | |
print(f'\n==== {k.name} tweets ====') | |
k.tweet('Begin at the beginning, and go on till you come to the end: then stop.') | |
print(f'\n==== {c.name} tweets ====') | |
c.tweet("We're all mad here.") | |
print(f'\n==== {h.name} tweets ====') | |
h.tweet('Why is a raven like a writing-desk?') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment