Skip to content

Commit 8e167b1

Browse files
committed
Chapter 14
1 parent 842802b commit 8e167b1

6 files changed

Lines changed: 217 additions & 0 deletions

File tree

Ch14/cafe_queue_abc.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
from collections.abc import Collection, Iterator
2+
from abc import abstractmethod
3+
4+
5+
class CustomerQueue(Collection):
6+
7+
@abstractmethod
8+
def add_customer(self, customer): pass
9+
10+
@property
11+
@abstractmethod
12+
def first(self): pass
13+
14+
15+
class CafeQueue(CustomerQueue):
16+
17+
def __init__(self):
18+
self._queue = []
19+
self._orders = {}
20+
self._togo = {}
21+
22+
def __iter__(self):
23+
return Iterator_CafeQueue(self)
24+
25+
def __len__(self):
26+
return len(self._queue)
27+
28+
def __contains__(self, customer):
29+
return (customer in self._queue)
30+
31+
def add_customer(self, customer, *orders, to_go=True):
32+
self._queue.append(customer)
33+
self._orders[customer] = tuple(orders)
34+
self._togo[customer] = to_go
35+
36+
@property
37+
def first(self):
38+
return self._queue[0]
39+
40+
41+
class Iterator_CafeQueue(Iterator):
42+
43+
def __init__(self, iterable):
44+
self._iterable = iterable
45+
self._position = 0
46+
47+
def __next__(self):
48+
if self._position >= len(self._iterable):
49+
raise StopIteration
50+
51+
customer = self._iterable._queue[self._position]
52+
orders = self._iterable._orders[customer]
53+
togo = self._iterable._togo[customer]
54+
55+
self._position += 1
56+
57+
return (customer, orders, togo)
58+
59+
def __iter__(self):
60+
return self
61+
62+
63+
def serve_customers(queue):
64+
if not isinstance(queue, CustomerQueue):
65+
raise TypeError("serve_next() requires a customer queue.")
66+
67+
if not len(queue):
68+
print("Queue is empty.")
69+
return
70+
71+
def brew(order):
72+
print(f"(Making {order}...)")
73+
74+
for customer, orders, to_go in queue:
75+
for order in orders: brew(order)
76+
if to_go:
77+
print(f"Order for {customer}!")
78+
else:
79+
print(f"(Takes order to {customer})")
80+
81+
82+
queue = CafeQueue()
83+
queue.add_customer('Raquel', 'double macchiato', to_go=False)
84+
queue.add_customer('Naomi', 'large mocha, skim')
85+
queue.add_customer('Anmol', 'mango lassi')
86+
87+
print(f"The first person in line is {queue.first}.")
88+
serve_customers(queue)

Ch14/classes_from_type.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
Food = type('Food', (), {})
2+
3+
4+
def __init__(obj, toppings):
5+
obj.toppings = toppings
6+
7+
8+
Pizza = type('Pizza', (Food,), {'name': 'pizza', '__init__': __init__})
9+
10+
print(Pizza.name) # 'name' is a class attribute
11+
pizza = Pizza(['sausage', 'garlic']) # instantiate like normal
12+
print(pizza.toppings) # prints "['sausage', 'garlic']"

Ch14/metaclass.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
class Gadget(type):
2+
3+
def __new__(self, name, bases, namespace):
4+
print(f"Creating a {name} gadget!")
5+
return super().__new__(self, name, bases, namespace)
6+
7+
@classmethod
8+
def __prepare__(cls, name, bases):
9+
return {'color': 'white'}
10+
11+
12+
class Thingamajig(metaclass=Gadget):
13+
def __init__(self, widget):
14+
self.widget = widget
15+
16+
def frob(self):
17+
print(f"Frobbing {self.widget}.")
18+
19+
20+
thing = Thingamajig("button") # also prints "Creating Thingamajig gadget!"
21+
thing.frob() # prints "Frobbing button"
22+
23+
print(Thingamajig.color) # prints "white"
24+
print(thing.__class__) # prints "<class '__main__.Thingamajig'>"

Ch14/palindrome_check.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
from abc import ABC, abstractmethod
2+
from collections.abc import Sequence
3+
4+
5+
class Palindromable(ABC):
6+
7+
@abstractmethod
8+
def __reversed__(self): pass
9+
10+
@abstractmethod
11+
def __iter__(self): pass
12+
13+
@abstractmethod
14+
def __str__(self): pass
15+
16+
17+
class LetterPalindrome(Palindromable):
18+
19+
def __init__(self, string):
20+
self._raw = string
21+
self._stripped = ''.join(filter(str.isalpha, string.lower()))
22+
23+
def __str__(self):
24+
return self._raw
25+
26+
def __iter__(self):
27+
return self._stripped.__iter__()
28+
29+
def __reversed__(self):
30+
return reversed(self._stripped)
31+
32+
@classmethod
33+
def __subclasshook__(cls, C):
34+
if issubclass(C, Sequence):
35+
return True
36+
return NotImplemented
37+
38+
39+
def check_palindrome(sequence):
40+
41+
if not isinstance(sequence, Palindromable):
42+
raise TypeError("Cannot check for palindrome on that type.")
43+
44+
for c, r in zip(sequence, reversed(sequence)):
45+
if c != r:
46+
print(f"NON-PALINDROME: {sequence}")
47+
return False
48+
print(f"PALINDROME: {sequence}")
49+
return True
50+
51+
52+
canal = LetterPalindrome("A man, a plan, a canal - Panama!")
53+
print(check_palindrome(canal)) # prints 'True'
54+
55+
bolton = LetterPalindrome("Bolton")
56+
print(check_palindrome(bolton)) # prints 'False'
57+
58+
print(check_palindrome([1, 2, 3, 2, 1])) # prints 'True'
59+
print(check_palindrome((1, 2, 3, 2, 1))) # prints 'True'
60+
61+
print(check_palindrome('racecar')) # prints 'True'
62+
print(check_palindrome('race car')) # prints 'False'
63+
print(check_palindrome(LetterPalindrome('race car'))) # prints 'True'
64+
65+
print(check_palindrome({1, 2, 3, 2, 1})) # raises TypeError

Ch14/product_of_thirds.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from collections.abc import Sequence
2+
from numbers import Complex
3+
4+
5+
def product_of_thirds(sequence):
6+
if not isinstance(sequence, Sequence):
7+
raise ValueError("Argument must be a sequence.")
8+
if not isinstance(sequence[0], Complex):
9+
raise TypeError("Sequence elements must support multiplication.")
10+
11+
r = sequence[0]
12+
for i in sequence[1::3]:
13+
r *= i
14+
return r
15+
16+
17+
print(product_of_thirds(range(1, 50))) # prints '262134882788466688000'
18+
print(product_of_thirds("Foobarbaz")) # raises TypeError

Ch14/types.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
print(type("Hello")) # prints "<class 'str'>"
2+
print(type(123)) # prints "<class 'int'>"
3+
4+
class Thing: pass
5+
print(type(Thing)) # prints "<class 'type'>"
6+
7+
something = Thing()
8+
print(type(something)) # prints "<class '__main__.Thing'>"
9+
10+
print(type(type)) # prints "<class 'type'>"

0 commit comments

Comments
 (0)