├── README.md ├── Section 2 ├── singleton_modules │ ├── a_single_var.py │ ├── mod2.py │ └── mod1.py ├── borg.py ├── singleton.py ├── prototype.py ├── factory.py ├── abstract_factory.py └── builder.py ├── Section 1 ├── 01_03 │ ├── iterators.py │ ├── generator.py │ ├── list_comp.py │ └── timer_wrapper.py └── 01_04 │ ├── multiple_inheritance.py │ └── inheritance.py ├── Section 3 ├── 03_03 │ ├── __pycache__ │ │ ├── proxy_1.cpython-36.pyc │ │ └── proxy_2.cpython-36.pyc │ ├── proxy_2.py │ └── proxy_1.py ├── 03_01 │ ├── example_page.html │ └── mvc.py ├── decorator.py ├── facade.py └── adapter.py ├── Section 5 ├── reactive.py ├── memento.py ├── template.py ├── observer.py └── strategy.py ├── Section 4 ├── state.py ├── interpreter.py ├── chain.py └── command.py ├── LICENSE └── Section 6 └── spaghetti.py /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # Python-Design-Patterns -------------------------------------------------------------------------------- /Section 2/singleton_modules/a_single_var.py: -------------------------------------------------------------------------------- 1 | only_one = "I'm the only one" 2 | -------------------------------------------------------------------------------- /Section 2/singleton_modules/mod2.py: -------------------------------------------------------------------------------- 1 | from singleton_modules import a_single_var 2 | 3 | print(a_single_var.only_one) 4 | -------------------------------------------------------------------------------- /Section 1/01_03/iterators.py: -------------------------------------------------------------------------------- 1 | list = [1,2,3] 2 | for i in list: 3 | print(i) 4 | iter = list.__iter 5 | iter.__next__() 6 | -------------------------------------------------------------------------------- /Section 2/borg.py: -------------------------------------------------------------------------------- 1 | class Borg: 2 | __shared_state = {} 3 | def __init__(self): 4 | self.__dict__ = self.__shared_state 5 | -------------------------------------------------------------------------------- /Section 2/singleton_modules/mod1.py: -------------------------------------------------------------------------------- 1 | from singleton_modules import a_single_var 2 | 3 | print(a_single_var.only_one) 4 | a_single_var.only_one += ' modified' 5 | -------------------------------------------------------------------------------- /Section 3/03_03/__pycache__/proxy_1.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Python-Design-Patterns/HEAD/Section 3/03_03/__pycache__/proxy_1.cpython-36.pyc -------------------------------------------------------------------------------- /Section 3/03_03/__pycache__/proxy_2.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Python-Design-Patterns/HEAD/Section 3/03_03/__pycache__/proxy_2.cpython-36.pyc -------------------------------------------------------------------------------- /Section 1/01_03/generator.py: -------------------------------------------------------------------------------- 1 | def fib_list(max): 2 | numbers = [] 3 | a, b = 0, 1 4 | while a < max: 5 | numbers.append(a) 6 | a, b = b, a + b 7 | return numbers 8 | -------------------------------------------------------------------------------- /Section 3/03_01/example_page.html: -------------------------------------------------------------------------------- 1 | {% for entry in entries %} 2 |
  • 3 |

    {{ entry.title }}

    4 |
    {{ entry.text|safe }}
    5 |
  • 6 | {% else %} 7 |
  • No entries yet.
  • 8 | {% endfor %} 9 | -------------------------------------------------------------------------------- /Section 1/01_03/list_comp.py: -------------------------------------------------------------------------------- 1 | numbers = [1,2,3,4,5] 2 | numbers_again = [n for n in numbers] 3 | even_numbers = [n for n in numbers if n%2 == 0] 4 | odd_squares = [n**2 for n in numbers if n%2 == 1] 5 | matrix = [[1,2,3], [4,5,6], [7,8,9]] 6 | flattened_matrix = [n for row in x for n in row] 7 | -------------------------------------------------------------------------------- /Section 2/singleton.py: -------------------------------------------------------------------------------- 1 | class Singleton: 2 | __instance = None 3 | def __new__(cls, val=None): 4 | if Singleton.__instance is None: 5 | Singleton.__instance = object.__new__(cls) 6 | Singleton.__instance.val = val 7 | return Singleton.__instance 8 | -------------------------------------------------------------------------------- /Section 5/reactive.py: -------------------------------------------------------------------------------- 1 | from rx import Observer 2 | 3 | class MyObserver(Observer): 4 | def on_next(self, x): 5 | print("Got: %s" % x) 6 | 7 | def on_error(self, e): 8 | print("Got error: %s" % e) 9 | 10 | def on_completed(self): 11 | print("Sequence completed") 12 | -------------------------------------------------------------------------------- /Section 3/03_01/mvc.py: -------------------------------------------------------------------------------- 1 | @app.route('/') 2 | def example_page(): 3 | """Searches the database for entries, then displays them.""" 4 | db = get_db() 5 | query = db.execute('select * from entries order by id desc') 6 | entries = query.fetchall() 7 | return render_template('example_page.html', entries=entries) 8 | -------------------------------------------------------------------------------- /Section 1/01_04/multiple_inheritance.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | def __init__(self): 3 | print('A') 4 | 5 | @staticmethod 6 | def foo(): 7 | print('foo') 8 | 9 | class B(object): 10 | def __init__(self): 11 | print('B') 12 | 13 | @staticmethod 14 | def bar(): 15 | print('bar') 16 | 17 | class C(A,B): 18 | def foobar(self): 19 | self.foo() 20 | self.bar() 21 | -------------------------------------------------------------------------------- /Section 2/prototype.py: -------------------------------------------------------------------------------- 1 | from copy import deepcopy 2 | 3 | class Point: 4 | def __init__(self, x, y): 5 | self.x = x 6 | self.y = y 7 | 8 | def __str__(self): 9 | print("({}, {})".format(self.x, self.y)) 10 | 11 | def move(self, x, y): 12 | self.x += x 13 | self.y += y 14 | 15 | def clone(self, move_x, move_y): 16 | obj = deepcopy(self) 17 | obj.move(move_x, move_y) 18 | 19 | return obj 20 | -------------------------------------------------------------------------------- /Section 1/01_03/timer_wrapper.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | def timing_function(some_function): 4 | def wrapper(): 5 | t1 = time.time() 6 | some_function() 7 | t2 = time.time() 8 | print("Time it took to run the function: " + str((t2 - t1)) + "\n") 9 | return wrapper 10 | 11 | @timing_function 12 | def my_function(): 13 | num_list = [] 14 | for num in (range(0, 10000)): 15 | num_list.append(num) 16 | print("\nSum of all the numbers: " + str((sum(num_list)))) 17 | -------------------------------------------------------------------------------- /Section 2/factory.py: -------------------------------------------------------------------------------- 1 | class ShapeInterface: 2 | def draw(self): pass 3 | 4 | 5 | class Circle(ShapeInterface): 6 | def draw(self): 7 | print("Circle.draw") 8 | 9 | 10 | class Square(ShapeInterface): 11 | def draw(self): 12 | print("Square.draw") 13 | 14 | 15 | class ShapeFactory: 16 | @staticmethod 17 | def getShape(type): 18 | if type == 'Cirle': 19 | return Circle() 20 | if type == 'Square': 21 | return Square() 22 | assert 0, "Could not find shape " + type 23 | -------------------------------------------------------------------------------- /Section 3/03_03/proxy_2.py: -------------------------------------------------------------------------------- 1 | class Blog: 2 | def read(self): 3 | print('Read the blog') 4 | 5 | def write(self): 6 | print('Write the blog') 7 | 8 | class Proxy: 9 | def __init__(self, target): 10 | self.target = target 11 | 12 | def __getattr__(self, attr): 13 | return getattr(self.target, attr) 14 | 15 | class AnonUserBlogProxy(Proxy): 16 | def __init__(self, blog): 17 | super().__init__(blog) 18 | def write(self): 19 | print('Only authorized users can write blog posts.') 20 | -------------------------------------------------------------------------------- /Section 1/01_04/inheritance.py: -------------------------------------------------------------------------------- 1 | class Pet(object): 2 | """Base class for all pets""" 3 | def __init__(self, name, species): 4 | self.name = name 5 | self.species = species 6 | 7 | def getName(self): 8 | return self.name 9 | 10 | def getSpecies(self): 11 | return self.species 12 | 13 | def __str__(self): 14 | return "%s is a %s" % (self.name, self.species) 15 | 16 | class Dog(Pet): 17 | 18 | def __init__(self, name, chases_cats): 19 | super().__init__(name, "Dog") 20 | self.chases_cats = chases_cats 21 | 22 | def chasesCats(self): 23 | return self.chases_cats 24 | 25 | def __str__(self): 26 | additional_info = "" 27 | if self.chases_cats: 28 | additional_info = " who chases cats" 29 | return super().__str__() + additional_info 30 | -------------------------------------------------------------------------------- /Section 5/memento.py: -------------------------------------------------------------------------------- 1 | import copy 2 | 3 | class Memento: 4 | 5 | def __init__(self, data): 6 | # make a deep copy of every variable in the given class 7 | for attribute in vars(data): 8 | setattr(self, attribute, copy.deepcopy(getattr(data, attribute))) 9 | 10 | 11 | class Undoable: 12 | 13 | def __init__(self): 14 | # each instance keeps the latest saved copy so that there is only one 15 | # copy of each in memory 16 | self.__last = None 17 | 18 | def save(self): 19 | self.__last = Memento(self) 20 | 21 | def undo(self): 22 | for attribute in vars(self): 23 | setattr(self, attribute, getattr(self.__last, attribute)) 24 | 25 | 26 | class Data(Undoable): 27 | 28 | def __init__(self): 29 | super(Data, self).__init__() 30 | self.numbers = [] 31 | -------------------------------------------------------------------------------- /Section 3/03_03/proxy_1.py: -------------------------------------------------------------------------------- 1 | class SubjectInterface: 2 | """ 3 | Define the common interface for RealSubject and Proxy so that a 4 | Proxy can be used anywhere a RealSubject is expected. 5 | """ 6 | def request(self): pass 7 | 8 | 9 | class Proxy(SubjectInterface): 10 | """ 11 | Maintain a reference that lets the proxy access the real subject. 12 | Provide an interface identical to Subject's. 13 | """ 14 | 15 | def __init__(self, real_subject): 16 | self._real_subject = real_subject 17 | 18 | def request(self): 19 | print("Proxy may be doing something, like controlling request access") 20 | self._real_subject.request() 21 | 22 | 23 | class RealSubject(SubjectInterface): 24 | """ 25 | Define the real object that the proxy represents. 26 | """ 27 | 28 | def request(self): 29 | print("The real thing is dealing with the request") 30 | -------------------------------------------------------------------------------- /Section 5/template.py: -------------------------------------------------------------------------------- 1 | class MakeMeal: 2 | 3 | def buy_ingredients(self, money): 4 | if money < self.cost: 5 | assert 0, 'Not enough money to buy ingredients!' 6 | 7 | def prepare(self): 8 | pass 9 | 10 | def cook(self): 11 | pass 12 | 13 | def go(self, money): 14 | self.buy_ingredients(money) 15 | self.prepare() 16 | self.cook() 17 | 18 | class MakePizza(MakeMeal): 19 | def __init__(self): 20 | self.cost = 3 21 | 22 | def prepare(self): 23 | print("Prepare Pizza - make the dough and add toppings") 24 | 25 | def cook(self): 26 | print("Cook Pizza - cook in the oven on gas mark 8 for 10 minutes") 27 | 28 | class MakeCake(MakeMeal): 29 | def __init__(self): 30 | self.cost = 2 31 | 32 | def prepare(self): 33 | print("Prepare Cake - mix ingredients together and pour into a cake tin") 34 | 35 | def cook(self): 36 | print("Cook Cake - bake in the oven on gas mark 6 for 20 minutes") 37 | -------------------------------------------------------------------------------- /Section 4/state.py: -------------------------------------------------------------------------------- 1 | # Base state class 2 | class ComputerState: 3 | name = "state" 4 | allowed = [] 5 | 6 | def switch(self, state): 7 | """ Switch to new state """ 8 | if state.name in self.allowed: 9 | print ('Current:', self ,' => switched to new state', state.name) 10 | self.__class__ = state 11 | else: 12 | print('Current:', self ,' => switching to', state.name, 'not possible.') 13 | 14 | def __str__(self): 15 | return self.name 16 | 17 | class Off(ComputerState): 18 | name = "off" 19 | allowed = ['on'] 20 | 21 | class On(ComputerState): 22 | name = "on" 23 | allowed = ['off','suspend','hibernate'] 24 | 25 | class Suspend(ComputerState): 26 | name = "suspend" 27 | allowed = ['on'] 28 | 29 | class Hibernate(ComputerState): 30 | name = "hibernate" 31 | allowed = ['on'] 32 | 33 | class Computer: 34 | def __init__(self): 35 | self.state = Off() 36 | 37 | def change(self, state): 38 | self.state.switch(state) 39 | -------------------------------------------------------------------------------- /Section 5/observer.py: -------------------------------------------------------------------------------- 1 | class Observable: 2 | 3 | def __init__(self): 4 | self.observers = [] 5 | 6 | def register(self, observer): 7 | if not observer in self.observers: 8 | self.observers.append(observer) 9 | 10 | def unregister(self, observer): 11 | if observer in self.observers: 12 | self.observers.remove(observer) 13 | 14 | def unregister_all(self): 15 | if self.observers: 16 | del self.observers[:] 17 | 18 | def update_observers(self, *args, **kwargs): 19 | for observer in self.observers: 20 | observer.update(*args, **kwargs) 21 | 22 | 23 | class Observer: 24 | def update(self, *args, **kwargs): 25 | pass 26 | 27 | 28 | class AmericanStockMarket(Observer): 29 | def update(self, *args, **kwargs): 30 | print("American stock market received: {0}\n{1}".format(args, kwargs)) 31 | 32 | 33 | class EuropeanStockMarket(Observer): 34 | def update(self, *args, **kwargs): 35 | print("European stock market received: {0}\n{1}".format(args, kwargs)) 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Packt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Section 4/interpreter.py: -------------------------------------------------------------------------------- 1 | class Expression: 2 | def interpret(self, text): pass 3 | 4 | 5 | class TerminalExpression(Expression): 6 | def __init__(self, word): 7 | self.word = word 8 | 9 | def interpret(self, text): 10 | words = text.split() 11 | if self.word in text: 12 | return True 13 | else: 14 | return False 15 | 16 | 17 | class OrExpression(Expression): 18 | def __init__(self, exp1, exp2): 19 | self.exp1 = exp1 20 | self.exp2 = exp2 21 | 22 | def interpret(self, text): 23 | return self.exp1.interpret(text) or self.exp2.interpret(text) 24 | 25 | 26 | class AndExpression(Expression): 27 | def __init__(self, exp1, exp2): 28 | self.exp1 = exp1 29 | self.exp2 = exp2 30 | 31 | def interpret(self, text): 32 | return self.exp1.interpret(text) and self.exp2.interpret(text) 33 | 34 | 35 | john = TerminalExpression('John') 36 | henry = TerminalExpression('Henry') 37 | mary = TerminalExpression('Mary') 38 | sarah = TerminalExpression('Sarah') 39 | 40 | # construct the rule sarah and (mary or (john and henry)) 41 | -------------------------------------------------------------------------------- /Section 3/decorator.py: -------------------------------------------------------------------------------- 1 | class WindowInterface: 2 | def build(self): pass 3 | 4 | 5 | class AbstractWindowDecorator(WindowInterface): 6 | """ 7 | Maintain a reference to a Window object and define an interface 8 | that conforms to Window's interface. 9 | """ 10 | 11 | def __init__(self, window): 12 | self._window = window 13 | 14 | def build(self): pass 15 | 16 | 17 | class Window(WindowInterface): 18 | def build(self): 19 | print("Building window") 20 | 21 | 22 | class BorderDecorator(AbstractWindowDecorator): 23 | def add_border(self): 24 | print("Adding border") 25 | 26 | def build(self): 27 | self.add_border() 28 | self._window.build() 29 | 30 | 31 | class VerticalSBDecorator(AbstractWindowDecorator): 32 | def add_vertical_scroll_bar(self): 33 | print("Adding vertical scroll bar") 34 | 35 | def build(self): 36 | self.add_vertical_scroll_bar() 37 | self._window.build() 38 | 39 | 40 | class HorizontalSBDecorator(AbstractWindowDecorator): 41 | def add_horizontal_scroll_bar(self): 42 | print("Adding horizontal scroll bar") 43 | 44 | def build(self): 45 | self.add_horizontal_scroll_bar() 46 | self._window.build() 47 | -------------------------------------------------------------------------------- /Section 3/facade.py: -------------------------------------------------------------------------------- 1 | class Engine: 2 | 3 | def __init__(self): 4 | # how much the motor is spinning in revs per minute 5 | self.spin = 0 6 | 7 | def start(self, spin): 8 | self.spin = min(spin, 3000) 9 | 10 | class StarterMotor: 11 | 12 | def __init__(self): 13 | # how much the starter motor is spinning in revs per minute 14 | self.spin = 0 15 | 16 | def start(self, charge): 17 | # if there is enough power then spin fast 18 | if (charge > 50): 19 | self.spin = 2500 20 | 21 | class Battery: 22 | 23 | def __init__(self): 24 | # % charged, starts flat 25 | self.charge = 0 26 | 27 | class Car: 28 | # the facade object that deals with the battery, engine and starter motor. 29 | 30 | def __init__(self): 31 | self.battery = Battery() 32 | self.starter = StarterMotor() 33 | self.engine = Engine() 34 | 35 | def turn_key(self): 36 | self.starter.start(self.battery.charge) 37 | self.engine.start(self.starter.spin) 38 | if (self.engine.spin > 0): 39 | print('Engine started') 40 | else: 41 | print('Engine not started') 42 | 43 | def jump(self): 44 | self.battery.charge = 100 45 | print('Jumped') 46 | -------------------------------------------------------------------------------- /Section 4/chain.py: -------------------------------------------------------------------------------- 1 | class Car: 2 | def __init__(self, name, water, fuel, oil): 3 | self.name = name 4 | self.water = water 5 | self.fuel = fuel 6 | self.oil = oil 7 | 8 | def is_fine(self): 9 | if self.water >= 20 and self.fuel >= 5 and self.oil >= 10: 10 | print('Car is good to go') 11 | return True 12 | else: 13 | return False 14 | 15 | 16 | class Handler: 17 | def __init__(self, successor=None): 18 | self._successor = successor 19 | 20 | def handle_request(self, car): 21 | if not car.is_fine() and self._successor is not None: 22 | self._successor.handle_request(car) 23 | 24 | 25 | class WaterHandler(Handler): 26 | 27 | def handle_request(self, car): 28 | if car.water < 20: 29 | car.water = 100 30 | print('Added water') 31 | super().handle_request(car) 32 | 33 | 34 | class FuelHandler(Handler): 35 | 36 | def handle_request(self, car): 37 | if car.fuel < 5: 38 | car.fuel = 100 39 | print('Added fuel') 40 | super().handle_request(car) 41 | 42 | 43 | class OilHandler(Handler): 44 | 45 | def handle_request(self, car): 46 | if car.oil < 10: 47 | car.oil = 100 48 | print('Added oil') 49 | super().handle_request(car) 50 | -------------------------------------------------------------------------------- /Section 2/abstract_factory.py: -------------------------------------------------------------------------------- 1 | # === abstract shape classes === 2 | class Shape2DInterface: 3 | def draw(self): pass 4 | 5 | class Shape3DInterface: 6 | def build(self): pass 7 | 8 | # === concrete shape classes === 9 | class Circle(Shape2DInterface): 10 | def draw(self): 11 | print("Circle.draw") 12 | 13 | class Square(Shape2DInterface): 14 | def draw(self): 15 | print("Square.draw") 16 | 17 | class Sphere(Shape3DInterface): 18 | def build(self): 19 | print("Sphere.build") 20 | 21 | class Cube(Shape3DInterface): 22 | def build(self): 23 | print("Cube.build") 24 | 25 | 26 | # === Abstract shape factory === 27 | class ShapeFactoryInterface: 28 | def getShape(sides): pass 29 | 30 | # === Concrete shape factories === 31 | class Shape2DFactory(ShapeFactoryInterface): 32 | @staticmethod 33 | def getShape(sides): 34 | if sides == 1: 35 | return Circle() 36 | if sides == 4: 37 | return Square() 38 | assert 0, "Bad 2D shape creation: shape not defined for " + sides + "sides" 39 | 40 | class Shape3DFactory(ShapeFactoryInterface): 41 | @staticmethod 42 | def getShape(sides): 43 | """here, sides refers to the number of faces""" 44 | if sides == 1: 45 | return Sphere() 46 | if sides == 6: 47 | return Cube() 48 | assert 0, "Bad 3D shape creation: shape not defined for " + sides + "faces" 49 | -------------------------------------------------------------------------------- /Section 3/adapter.py: -------------------------------------------------------------------------------- 1 | # Adaptee (source) interface 2 | class EuropeanSocketInterface: 3 | def voltage(self): pass 4 | def live(self): pass 5 | def neutral(self): pass 6 | def earth(self): pass 7 | 8 | # Target interface 9 | class USASocketInterface: 10 | def voltage(self): pass 11 | def live(self): pass 12 | def neutral(self): pass 13 | 14 | # Adaptee 15 | class EuropeanSocket(EuropeanSocketInterface): 16 | def voltage(self): 17 | return 230 18 | 19 | def live(self): 20 | return 1 21 | 22 | def neutral(self): 23 | return -1 24 | 25 | def earth(self): 26 | return 0 27 | 28 | # Client 29 | class AmericanKettle: 30 | __power = None 31 | 32 | def __init__(self, power): 33 | self.__power = power 34 | 35 | def boil(self): 36 | if self.__power.voltage() > 110: 37 | print("Kettle on fire!") 38 | else: 39 | if self.__power.live() == 1 and self.__power.neutral() == -1: 40 | print("Coffee time!") 41 | else: 42 | print("No power.") 43 | 44 | class Adapter(USASocketInterface): 45 | __socket = None 46 | 47 | def __init__(self, socket): 48 | self.__socket = socket 49 | 50 | def voltage(self): 51 | return 110 52 | 53 | def live(self): 54 | return self.__socket.live() 55 | 56 | def neutral(self): 57 | return self.__socket.neutral() 58 | -------------------------------------------------------------------------------- /Section 6/spaghetti.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | def play_blackjack(draw_if_less_than): 4 | 5 | deck = [] 6 | hand = [] 7 | dealer = [] 8 | handTotal = 0 9 | handDealer = 0 10 | 11 | # Create single-digit cards 12 | for i in range(2, 10): 13 | a = i 14 | deck.append(a) 15 | 16 | # Create 10 cards 17 | count_1 = 16 18 | while count_1 > 0: 19 | deck.append(10) 20 | count_1 -= 1 21 | 22 | # Create aces 23 | count_2 = 4 24 | while count_2 > 0: 25 | deck.append(11) 26 | count_2 -= 1 27 | 28 | # Set up 2 hand for yourself 29 | while len(hand) < 2: 30 | drawCard = random.choice(deck) 31 | hand.append(drawCard) 32 | deck.remove(drawCard) 33 | handTotal += drawCard 34 | 35 | # Set up 2 hand for the dealer 36 | while len(dealer) < 2: 37 | drawCard = random.choice(deck) 38 | dealer.append(drawCard) 39 | deck.remove(drawCard) 40 | handDealer += drawCard 41 | 42 | # Hit or stand descision 43 | while handTotal < draw_if_less_than: 44 | drawCard = random.choice(deck) 45 | hand.append(drawCard) 46 | deck.remove(drawCard) 47 | handTotal += drawCard 48 | print(hand) 49 | 50 | # Dealer moves 51 | while handDealer <= 17: 52 | drawCard = random.choice(deck) 53 | dealer.append(drawCard) 54 | deck.remove(drawCard) 55 | handDealer += drawCard 56 | print(dealer) 57 | 58 | print(handTotal) 59 | print(handDealer) 60 | -------------------------------------------------------------------------------- /Section 5/strategy.py: -------------------------------------------------------------------------------- 1 | class PrimeFinder: 2 | 3 | def __init__(self): 4 | self.primes = [] 5 | 6 | def calculate(self, limit): 7 | """ Will calculate all the primes below limit. """ 8 | pass 9 | 10 | def out(self): 11 | """ Prints the list of primes prefixed with which algorithm made it """ 12 | print(self.__class__.__name__) 13 | for prime in self.primes: 14 | print(prime) 15 | 16 | 17 | class HardCodedPrimeFinder(PrimeFinder): 18 | def calculate(self, limit): 19 | hardcoded_primes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47] 20 | primes = [] 21 | for prime in hardcoded_primes: 22 | if (prime < limit): 23 | self.primes.append(prime) 24 | 25 | 26 | class StandardPrimeFinder(PrimeFinder): 27 | def calculate(self, limit): 28 | self.primes = [2] 29 | # check only odd numbers. 30 | for number in range(3, limit, 2): 31 | is_prime = True 32 | for prime in self.primes: 33 | if (number % prime == 0): 34 | is_prime = False 35 | break 36 | if (is_prime): 37 | self.primes.append(number) 38 | 39 | 40 | class PrimeFinderClient: 41 | 42 | def __init__(self, limit): 43 | self.limit = limit 44 | if limit <= 50: 45 | self.finder = HardCodedPrimeFinder() 46 | else: 47 | self.finder = StandardPrimeFinder() 48 | 49 | def get_primes(self): 50 | self.finder.calculate(self.limit) 51 | self.finder.out() 52 | -------------------------------------------------------------------------------- /Section 4/command.py: -------------------------------------------------------------------------------- 1 | class Screen(object): 2 | def __init__(self, text=''): 3 | self.text = text 4 | self.clip_board = '' 5 | 6 | def cut(self, start=0, end=0): 7 | self.clip_board = self.text[start:end] 8 | self.text = self.text[:start] + self.text[end:] 9 | 10 | def paste(self, offset=0): 11 | self.text = self.text[:offset] + self.clip_board + self.text[offset:] 12 | 13 | def clear_clipboard(self): 14 | self.clip_board = '' 15 | 16 | def length(self): 17 | return len(self.text) 18 | 19 | def __str__(self): 20 | return self.text 21 | 22 | 23 | # Screen command interface 24 | class ScreenCommand: 25 | def __init__(self, screen): 26 | self.screen = screen 27 | self.previous_state = screen.text 28 | 29 | def execute(self): 30 | pass 31 | 32 | def undo(self): 33 | pass 34 | 35 | 36 | class CutCommand(ScreenCommand): 37 | def __init__(self, screen, start=0, end=0): 38 | super().__init__(screen) 39 | self.start = start 40 | self.end = end 41 | 42 | def execute(self): 43 | self.screen.cut(start=self.start, end=self.end) 44 | 45 | def undo(self): 46 | self.screen.clear_clipboard() 47 | self.screen.text = self.previous_state 48 | 49 | 50 | class PasteCommand(ScreenCommand): 51 | def __init__(self, screen, offset=0): 52 | super().__init__(screen) 53 | self.offset = offset 54 | 55 | def execute(self): 56 | self.screen.paste(offset=self.offset) 57 | 58 | def undo(self): 59 | self.screen.clear_clipboard() 60 | self.screen.text = self.previous_state 61 | 62 | 63 | class ScreenInvoker: 64 | def __init__(self): 65 | self.history = [] 66 | 67 | def store_and_execute(self, command): 68 | command.execute() 69 | self.history.append(command) 70 | 71 | def undo_last(self): 72 | if self.history: 73 | self.history.pop().undo() 74 | -------------------------------------------------------------------------------- /Section 2/builder.py: -------------------------------------------------------------------------------- 1 | from copy import deepcopy 2 | 3 | class Car: 4 | def __init__(self): 5 | self.__wheels = list() 6 | self.__engine = None 7 | self.__body = None 8 | 9 | def setBody(self, body): 10 | self.__body = body 11 | 12 | def attachWheel(self, wheel): 13 | self.__wheels.append(wheel) 14 | 15 | def setEngine(self, engine): 16 | self.__engine = engine 17 | 18 | def specification(self): 19 | print("body: %s" % self.__body.shape) 20 | print("engine horsepower: %d" % self.__engine.horsepower) 21 | print("tire size: %d\'" % self.__wheels[0].size) 22 | 23 | def clone(self): 24 | return deepcopy(self) 25 | 26 | # === Car parts === 27 | class Wheel: 28 | size = None 29 | 30 | class Engine: 31 | horsepower = None 32 | 33 | class Body: 34 | shape = None 35 | 36 | 37 | class Director: 38 | __builder = None 39 | 40 | def setBuilder(self, builder): 41 | self.__builder = builder 42 | 43 | # The algorithm for assembling a car 44 | def getCar(self): 45 | car = Car() 46 | 47 | # First goes the body 48 | body = self.__builder.getBody() 49 | car.setBody(body) 50 | 51 | # Then engine 52 | engine = self.__builder.getEngine() 53 | car.setEngine(engine) 54 | 55 | # And four wheels 56 | i = 0 57 | while i < 4: 58 | wheel = self.__builder.getWheel() 59 | car.attachWheel(wheel) 60 | i += 1 61 | 62 | return car 63 | 64 | 65 | class BuilderInterface: 66 | def getWheel(self): pass 67 | def getEngine(self): pass 68 | def getBody(self): pass 69 | 70 | 71 | class JeepBuilder(BuilderInterface): 72 | def getWheel(self): 73 | wheel = Wheel() 74 | wheel.size = 22 75 | return wheel 76 | 77 | def getEngine(self): 78 | engine = Engine() 79 | engine.horsepower = 400 80 | return engine 81 | 82 | def getBody(self): 83 | body = Body() 84 | body.shape = "SUV" 85 | return body 86 | 87 | 88 | class NissanBuilder(BuilderInterface): 89 | def getWheel(self): 90 | wheel = Wheel() 91 | wheel.size = 16 92 | return wheel 93 | 94 | def getEngine(self): 95 | engine = Engine() 96 | engine.horsepower = 100 97 | return engine 98 | 99 | def getBody(self): 100 | body = Body() 101 | body.shape = "hatchback" 102 | return body 103 | --------------------------------------------------------------------------------