Skip to content

Instantly share code, notes, and snippets.

@ethmcc
Last active September 16, 2020 19:16
Show Gist options
  • Save ethmcc/095fe476e33c82e218f13e605a6455ef to your computer and use it in GitHub Desktop.
Save ethmcc/095fe476e33c82e218f13e605a6455ef to your computer and use it in GitHub Desktop.
Design Patterns in Python for the Untrained Eye
# 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