Python in Practice Flashcards

1
Q

Abstract Factory Pattern

Diagram with Svg and Text

A

Designed for situations where we want to create complex objects that are composed of other objects and where the composed objects are all of one particular “family.”

some gui:

has abstact widget factory with three subclass factories.

  1. MacWidgetFactory
  2. XfceWidgetFactory
  3. WindowsWidgetFactory

provide methods for creating the same objects:

  1. make_button()
  2. make_spinbox(), etc…

we can create a generic create_dialog() function that takes a factory instance as an argument and produces a dialog with OS X, Xfce, or windows dialog.

“Abstract” usually means the base class also serves as a concrete class in its own right, with other classes inheriting from it.

This abstract class will often contain methods which call subclasses specific to each class that inherits it. make_button() above will call subclasses for windows, Xfce, and Mac OS.

steps:

  1. One top level function calls a factories
  2. Abstract factory has class methods that call inner classes (Diagram, Rectangle, Text).
  3. More complex factory inherits simple one. Methods on abstract class call inner classes and reference private constants, which do all the work.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Builder Pattern

HTML and Tkinter forms

A

Similar to Abstract Factory in that both patterns are designed to create complex objects composed of other objects

Builder is distinct in that it not only contains methods for building the object, it also holds the representation of the entire complex object itself.

top level calls use the same function, parameterized by appropriate builder object.

>>> tkForm = create_login(TkFormBuilder())

>>> htmlForm = create_login(HtmlFormBuilder())

Both inherit from an abstract base class, AbstractForm - has a bunch of abstract methods

class AbstractForm(metaclass=abc.ABCMeta):

__@abc.abstractmethod

__def form(self):

____pass

any class inheriting this must implement all the abstract methods.

giving a class metaclass=abc.ABCMeta means the class cannot be instantiated. Sets “__abstractmethod__” attribute to true, returns original function

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Factory Method Pattern

gameboard

A

when we want subclasses to choose which subclass they should instantiate when an object is requested.

Good for lots of things, but also for when we can’t know the class in advance.

def make_new_method(char):

__def new(Class): # Can’t use super() or super(Piece, Class) b/c there is no instance/class context for super to access.

____return Piece.__new__(Class, char)

__return new

for code in itertools.chain((code1, code2), codes):

__char = chr(code)

__name = unicodedata.name(char).title().replace(“ “, “”)

__new = make_new_method(char)

__Class = type(name, (bases, ), dict(__slots__=(), __new__=new))

__setattr(sys.modules[__name__], name, Class)

or

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

example of nesting lambdas

what for?

A

new = (lambda char: lambda Class: Piece.__new__(Class, char))(char)

name is always ‘lambda’ - not good

new.__name__ = ‘__new__’

within the loop, char has meaning, but Class is a placeholder for when “__new__” is called on the class. We’ll create a new Piece class whos name is the name of the unicode character and who’s value is the characters representation. (game piece)

In the gameboard example, this allowed the dynamic creation of a function in a loop going through values to create classes for game pieces.

“new” was put in the __new__ slot of an attribute dict and called with the name and bases on “type”, then assigned to the global namespace.

Class = type(name, (Piece,), dict(__slots__=(), __new__=new))
globals()[name] = Class

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Prototype Pattern:

7 ways to make a class instance

A

even when names are only known at runtime, Python provides a variety of ways of creating new objects.

class Point:

__ __slots__ = (“x”, “y”)

__def __init__(self, x, y):

____self.x = x

____self.y = y

def make_object(Class, *args, **kwargs):

__return Class(*args, **kwargs)

point1 = Point(1, 2)

point2 = eval(“{}({}, {})”.format(“Point”, 2, 4) #risky

point3 = getattr(sys.modules[__name__], “Point”)(3, 6)

point4 = globals()“Point”

point5 = make_object(Point, 5, 10)

point6 = copy.deepcopy(point5)

point6. x = 6
point6. y = 12

point7 = point1.__class__(7, 14) # any previous instance would work here.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Singleton Pattern

A

used when the class has only a single instance that is the one and only needed throughout the program.

create a module with the global state that’s needed kept in private variables and access provided by public functions:

ex.

_URL = “http://www.bankofcanada.ca/stats/assets/csv/fx-seven-day.csv”

def get(refresh=False):

__if refresh:

____get.rates = {}

__if get.rates:

____return get.rates

__with urllib.request.urlopen(_URL) as file:

____for line in file:

______line = line.rstrip().decode(“utf-8”)

______if not line or line.startswith((“#”, “Date”)):

________continue

______name, currency, *rest = re.split(r’\s*, \s*’, line)

______key = “{}({})”.format(name, currency)

______try:

________get.rates[key] = float(rest[-1])

______except ValueError as err:

________print(“error {}: {}”.format(err, line)

__return get.rates

###

This is in the currency/Rates.py module. the rates dictionary is an attribute of of the Rates get() function - a private value. When the public get() function is called, the get function either returns the rates or fetches them anew. No class needed.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Structural Design Patterns

in Python

A

Primary goal of structural design patterns is how objecst are composed together to form new, larger objects. Three themes stand out in structural design patterns:

adapting interfaces, adding functionality and handling collections of objects.

  1. Adapter pattern
  2. Bridge pattern
  3. Composite pattern
  4. Decorator pattern
  5. Facade pattern
  6. Flyweight pattern
  7. Proxy pattern

Just remember “A B C D F F P”!

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Adapter pattern:

or “How to Duck Type”

Text and HTML rendering with a “Renderer” protocol

A

Technique for adapting an interface so one class can use another class (with an incompatible interface) without changing either of the classes being used.

a class need not know or care what the class of one of its arguments is, only that the given class provides the proper interface.

The page example: page class takes a “renderer” object that needs to inherit from class Renderer ( if not isinstance(renderer, Renderer)), which will mean it has the header, paragraph and footer methods. That’s all.

Duck typing solution (without requiring inheritance):

class Renderer(metaclass=abc.ABCMeta):

__@classmethod

__def __subclasshook__(Class, Subclass):

____if Class is Renderer:

______attributes = collections.ChainMap(*(Superclass.__dict__ for Superclass in Subclass.__mro__))

______methods = (“header”, “paragraph”, “footer”)

______if all(method in attributes for method in methods):

________return True

____return NotImplemented

**Explanation: **

isinstance(instance, Class) calls __subclasshook__ to see if the object given is a subclass of the second argument. So:

isinstance(renderer, Renderer) looks in Renderer for __subclasshook__, and determines if the stuff in the mro of the given renderer satisfies the criteria. The renderer need not actually subclass Renderer.

Qtrac.py has a has_methods(*methods) decorator that does this.

Likewise, you can inherit from Qtrac.requirer, an abstract base class

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Bridge Pattern

create class for drawing barcharts, but use other classes for actual rendering of the barcharts

A

Separates an abstraction (an interface or algorithm) from how it is implemented.

Conventionally, we’d create one or more abstract base classes and subclass them several times for our concrete implementations.

Bridges create independent class hierarchies:

  1. Abstract: defines the operations (interface and algorithms)
  2. Concrete: provides implementations that will be called

Abstract class aggregates an instance of one of the concrete implementation classes - this instance serves as a bridge between the abstract interface and the concrete operations.

From the book, HtmlRenderer (has the header, paragraph and footer methods) could be said to have used the bridge pattern, it aggregated an HtmlWriter (which was more complex than TextRenderer, requiring this class) to provide its rendering

class BarRenderer(Qtrack.Requirer):

__required_methods={“initialize”, “draw”, …}

class BarCharter:

__def __init__(self, renderer):

____if not isinstance(renderer, BarRenderer):

…..

__def render(self, caption, pairs): # only method

….

class TextBarRenderer:

__def __init__(self, scaleFactor=40):

____self.scaleFactor = scaleFactor

** define above required functions

class ImageBarRenderer:

__COLORS = # defines colors

** __init__ specific to needs w/ above rendering methods defined.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Bridge Pattern Example

A

define a class that checks if the concrete class passed to it has the appropriate methods.

this is done with:

if not isinstance(concrete, Abstract) …

the @Qtrac.has_methods works well to define the Abstract Base Class

@Qtrac.has_methods(‘method1’, ‘method2’)

class AbstractClass(metaclass=abc.ABCMeta): pass

###

Your concrete classes (the bridge between the abstract base class and the implementer) now need to implement methods 1 and 2, but they’ll be called when passing the class to the bridge class - for example, in the bridge classes’ “render” method, it calls the initialize, draw_caption, draw_bar, and finalize methods of the TextBarRenderer and ImageBarRenderer classes - each of which are very different.

class BarCharter: # the implementer

class BarRenderer(Qtrac.Requirer): # abstract

__required_methods = …

class TextBarRenderer: # bridge 1

class ImageBarRenderer: # bridge 2

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

Qtrac.has_methods

class decorator

because it’s cool

A

def has_methods(*methods):

__def decorator(Base):

____def __subclasshook__(Class, Subclass):

______if Class is Base:

________attributes = collections.ChainMap(*(Superclass.__dict__ for Superclass in Subclass.__mro__))

________if all(method in attributes for method in methods):

__________return True

______return NotImplemented

____Base.__subclasshook__ = classmethod(__subclasshook__)

____return Base

__return decorator

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

Composite Pattern

describe general idea and example used in book

A

Designed to support the uniform treatment of objects in a hierarchy, whether they contain other objects or not.

Composite and noncomposite objects normally have the same core methods, with composite objects having additional methods to support adding, removing, and iterating their children.

Often used in drawing programs like Inkscape to support grouping or ungrouping.

book used Stationary as an example:

  • each item had a name and a price.
  • items can be grouped in sets, the price of which is the sum of the contents prices.
  • These can be nested without limit.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

Classic Composite/Noncomposite Hierarchy

Stationary example, 2 Abstract classes

A

composite is abstract, subclasses must implement

Abstract Item base class:

class AbstractItem(metaclass=abc.ABCMeta):

__@abc.abstractproperty

__def composite(self):

____pass

__def __iter__(self):

____return iter([])

class SimpleItem(AbstractItem):

__def __init__(self, name, price = 0.00):

____self.name = name

____self.price = price

__@property

__def composite(self):

____return False

class AbstractCompositeItem(AbstractItem):

__def __init__(self, *items):

____self.children = []

____if items:

______self.add(*items)

there is plenty more, check out stationary 1

Basic idea:

Noncomposite base abstract class is used for items, Abstract Composite Class inherits from it and adds some methods for dealing with items.

Composite items must declare @properties to handle the methods from both bases. (AbstractItem and AbstractCompositeItem)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

Single Class for Composites

and Non-composites

no abstract class, bunch of classmethods and properties

A

decorate a couple class methods

create an Item class that can be either noncomposite or composite.

class Item:

def \_\_init\_\_(self, name, \*items, price=0.00):
     self.name = name
     self.price = price
     self.children = []
     if items:
         self.add(\*items)

@classmethod

def create(Class, name, price):

__return Item(name, price=price)

@classmethod

def compose(Class, name, *items):

__return Item(name, *items)

@property

def composite(self):

__return bool(self.children) # True if exists.

@property

def price(self):

__return (sum(item.price for item in self) if self.children else self.__price

@price.setter #using a setter function

def price(self, price):

__self.__price = price

there’s more. Check the code.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

Decorator Pattern

A

Decorators accept a function and return a function of the same name but with enhanced functionality.

classes, methods and functions can be decorated.

@functools.total_ordering:

class decorator that can be used on a class which implements __eq__() and __lt__() so it will have the full suite of comparison operators.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

Class Decorators

ensuring values of attributes

one decorator, several attribute validations

A

this requires stacking loads of decorators on top of one another. not optimal.

def ensure(name, validate, doc=None):

__def decorator(Class):

____privateName = “__” + name

____def getter(self):

______return getattr(self, privateName)

____def setter(self, value):

______validate(name, value)

______setattr(self, privateName, value)

____setattr(Class, name, property(getter, setter, doc=doc))

____return Class

__return decorator

property(getter, setter, deleter, doc)

@ensure(“title”, is_valid_title)

@ensure(“isbn”, is_valid_isbn)

class Book:

__def __init__(self, title, isbn):

____self.title = title

____self.isbn = isbn

__#book now has title and isbn property validators, so they’ll both be checked upon assignment and when changed

17
Q

Using a class decorator to add properties

one class handles attributes within class

decorator function accepts class and searches for attributes within class of a certain class.

A

@do_ensure

class Book:

__title = Ensure( is_non_empty_str)

__isbn = Ensure(is_valid_isbn)

__price = Ensure(is_in_range(1, 100000)

….

__def __init__(self, title, isbn, price,..)

etc.

class Ensure:

__def __init__(self, validate, doc=None):

____self.validate = validate

____self.doc = doc

def do_ensure(Class):

__def make_property(name, attribute):

____privateName = “__” + name

____def getter(self):

______return getattr(self, privateName)

____def setter(self):

______attribute.validate(name, value)

______setattr(self, privateName, value)

____return property(getter, setter, doc=attribute.doc)

__for name, attribute in Class.__dict__.items():

____if isinstance(attribute, Ensure):

______setattr(Class, name, make_property(name, attribute))

__return Class

18
Q

Using a class decorator instead of subclassing

describe 4 classes:

Mediator, Mediated, Button, Text

change Mediated to decorator

A
  1. Mediator takes a tuple of widget-callable pairs. When a thing happens to a widget, the callable calls with the widget as an argument. The widget’s mediator is set to be this class - a dictionary of key=widget, val=callable
  2. Mediated is a class that sets itself with no mediator and an on_change function that calls its own mediator’s on_change function (if it has a mediator)
  3. Button and Text inherit from Mediated. When we click the button or change the text (via @text.setter), the inherited on_change method fires.
  4. on_change() just calls it’s mediator’s (Mediator) on_change() function, which looks up what to do in it’s dictionary.

mediator1.py and mediator1d.py

mediated as decorator:

def mediated(Class):

__setattr(Class, “mediator”, None)

__def on_change(self):

____if self.mediator is not None:

______self.mediator.on_change(self)

__setattr(Class, “on_change”, on_change)

__return Class

@mediated

class Button:

same code

19
Q

Facade Pattern

pretty simple concept

A

Creates simplified interfaces on top of low level commands. Ideally the lower level interface will still be accessible, but we use the facade most of the time.

The example was a lengthy archive handler that dealt with .tar.gz, .tar.bz2, .tar.xc, and .zip files. It had a context manager:

def __enter__(self):

__return self

def __exit__(self, exc_type, exc_value, traceback):

__self.close()

and logic that forked flow according to the file extension, returning name methods (getnames for tar, namelist for zip), and appropriate file objects.

Similar to an adapter pattern in that they both provide simple interfaces, but a facade specifically masks a complicated interface, whereas the adapter is designed to create a unified interface on top of (not necessarily complicated) interfaces.

20
Q

Flyweight pattern

making points

shelve module

A

Designed to handle large numbers of relatively small objects.

Each unique object is represented once and shared wherever needed.

A dictionary is a simple implementation of the pattern

With a large number of (not necessarily small) objects, reducing the memory footprint can be achieved with __slots__.

class Point:

__ __slots__ = (‘x’, ‘y’, ‘z’, ‘color’)

__def __init__(self, x=0, y=0, z=0, color=None):

____self.x = x

etc…

because of __slots__, no point has its own private dict (self.__dict__). No arbitrary attributes can be added to Point.

using a static __dbm (class-level) variable and shelve is much more memory efficient, but takes longer. Learn later.

class Point:

__ __slots__ = (‘x’, ‘y’, ‘z’, ‘color’)

__ __dbm = shelve.open(os.path.join(“tmp”, “point.db”)

__def __init__(self, x=0, y=0, z=0, color=None):

____self.x = x

__def __key(self, name):

____return “:{}”.format(id(self), name)

__def __getattr__(self, name):

____return Point.__dbm[self.__key(name)]

__def __setattr__(self, name, value):

____Point.__dbm[self.__key(name)] = value

__atexit.register(__dbm.close) # uses atexit module

21
Q

Proxy Pattern

four examples with image processing

R, S, V, P

A

Used when we want one object to stand in for another.

  1. Remote proxy where a local object proxies a remote object (RPyC library)
  2. Smart reference that performs “additional actions when an object is accessed”.
  3. Virtual proxy that allows creation of lightweight objects instead of heavyweight, creating the latter if needed
  4. Protection proxy that provides different levels of access based on client access rights

Same coding approach can be used for all, but “Smart Reference” can be done with a @property decorator.

Also good for unit testing - ie. accessing resources that might not be available, or accessing incomplete class. Python 3 includes the unittest.mock library for creating mock objects and adding stubs in place of missing methods.

imageproxy1.py and imageproxy2.py

The Imageproxy class takes an Image.Image object with a specific interface and does not do the expensive rendering until it is saved or you ask it questions about the image (what’s the size, etc.)

commands are appended to self.commands in tuples of (function_name, *args)

so when it is time to execute, loop through self.commands like this:

for command in self.commands:

__command = self.commands.pop(0)

__func, *args = command

__image = func(*args)

__for command in self.commands:

____func, *args = command

____func(image, args)

__image.save(filename)

__return image

22
Q

Chain of Responsibility Pattern

A

or

Decouples sender of request from the recipient that processes the request.

Each handler has a successor, all the way to Null handler. (Wrap all in debug handler if needed)

handler1 = TimerHandler(KeyHandler(MouseHandler(NullHandler())))

while True:

__event = Event.next()

__if event.kind == Event.TERMINATE

____break

__pipeline.send(event)

__handler1.handle(event)

class MouseHandler(NullHandler):

__def handle(self, event):
____if event.kind == Event.MOUSE:
______print(“Click: {}”.format(event))
____else:
______super().handle(event)

super() calls NullHandler’s handle method, which is the current handler’s argument (the successor), if the event matches, the handler does it’s thing.

coroutine decorator

def coroutine(function):

__@functools.wraps(function)

__def wrapper(*args, **kwargs):

____generator = function(*args, **kwargs)

____next(generator)

____return generator

__return wrapper

####

@coroutine

def key_handler(successor=None):

__while True:

____event = (yield)

____if event.kind == Event.KEYPRESS:

______print(“press: {}”.format(event))

____elif successor is not None:

______successor.send(event) ## dunno where send comes from

23
Q

Name 11 Behavioral Patterns

A
  1. Chain of Responsibility - decouples sender of a request from the recipient
  2. Command - encapsulate commands as objects - handy for making things undoable
  3. Interpreter - formalizes two common requirements - means by which users enter non strings and program applications
  4. **Iterator **- sequentially acess items inside a collection without exposing any of the internals or the aggregate’s implementation
  5. Mediator - Provides means of creating an object - the mediator - that can encapsulate the interactions between other objects.
  6. Memento - Means of saving and restoring an object’s state without violating encapsulation.
  7. Observer - Supports many-to-many dependency relationships between objects. When one object changes state, all related objects are notified.
  8. State - Intended to provide objects whose behavior changes when their state changes - objects that have modes.
  9. Strategy - Provides means of encapsulating a set of algorithms that can be used interchangeably, depending on the user’s needs.
  10. Template - Allows us to define the steps of an algorithm but defer the execution of those steps to subclasses
  11. Visitor - Apply a function to every item in a collection or aggregate object. Different from the iterator only in perspective - we are applying an external function on each item.
    12.
24
Q

Command Pattern

like storing commands in ImageProxy example

A

storing sequence of commands works the similarly

create classes for undoable individual commands and for undoable macros. The basic idea is to store commands to be executed in succession at a later time, store the output at a given stage, reset it later if you want. Since callables are first class objects that can be passed around in lists or dicts, Python is a great language for this pattern.

  • Command.Command - takes do and undo callables and an optional description
  • Command.Macro - takes optional description and any number of Command.Command objects added

import Command ## Python in Practice module

def create_cell_command(self, x, y, color):

__def undo():

____self.cell(x, y, undo.color) # setter b/c color

__def do():

____undo.color = self.cell(x,y) # getter in closure

____self.cell(x, y, color) # setter b/c color

__return Command.Command(do, undo, “cell”)

25
Q

Interpreter Pattern

A

How to allow the user to enter non string data and how to let them program applications. (?)

here python safely parses two strings:

try:

__count = int(userCount)

__when = datetime.datetime.strptime(userDate, “%Y/%m/%d”).date()

except ValueError as err:

__print(err)

But maybe allowing trusted users access to the interpreter themselves? Use PLY or PyParsing.

Beats writing a Domain Specific Language (DSL - which is apparently doable out of the box).

Essentially:

  1. program makes a prompt using “input()” and passes the output to a function that knows the global and local contexts and adds the current context to the local
  2. rather than give it the whole global() context, it makes a function called global_context() that returns a subset of it
  3. calculate - evaluates the expression and prints the local context
  4. update - changes the name of the variable passed to localContext next time round
26
Q

Interpreter with exec() instead of eval()

A

exec() is not limited to a single expression and always returns None

context can be passed to exec() via locals and globals dicts.

genome1.py super simple

genome2.py and genome3.py

these are tricky, but revolve around using sys.Popen

def execute(code, context):

__module, offset = create_module(code.code, context)

__with subprocess.Popen([sys.executable, “-“], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) as process:

____communicate(process, code, module, offset)

genome3.py returns its results in a pickle

this pattern cannot protect from executing unsafe code

27
Q

Iterator Pattern

A

sequentially acess items inside a collection without exposing any of the internals or the aggregate’s implementation

three options:

  1. satisfy the sequence protocol
  2. two argument form of built-in iter()
  3. satisfy the iterator protocol

sequence

class AtoZ:

__def __getitem__(self, index):

____if 0 <= index < 26:

______return chr(index + ord(‘A’))

____raise IndexError()

for leter in iter(AtoZ()):….

two-arg iter():

for it in iter(callable, Sentinal_value):

__print(it)

print()

iter stops when callable returns a StopIteration or if it returns the sentinal value (eg. None)

iteration protocol:

define __iter__(self) using return or yield

uses a bag as an example. Python has a bag at collections.Counter

28
Q

Mediator Pattern

A

Provides means of creating an object - the mediator - that can encapsulate the interactions between other objects.

achieve interactions between objects that have no direct knowledge of each other.

When a button is clicked, the button just tells the mediator, which tells anything else that might be interested.

The examples are getting long, but this is good. Look at mediator examples.

These only show one-to-one widget-function relationships, but many-to-many is possible.

29
Q

Memento Pattern

A

Means of saving and restoring an object’s state without violating encapsulation.

pickle supports this out of the box. All python objects, (apart from file objects), can be pickled/unpickled.

when there is a limitation on pickle:

  • __setstate__() and __getstate__()
  • possibly __getnewargs__()

Unpickling involves executing arbitrary python code, so unpickling from untrusted sources is not an option. JSON is safer, or use checksums and encryption with pickling to ensure the pickle hasn’t been meddled with.

30
Q

Observer Pattern

Slider with History and LiveView observers

A

Supports many-to-many dependency relationships between objects. When one object changes state, all related objects are notified.

MVC paradigm is most common.

Controllers mediate between the input and model. When the model changes, the associated views change.

In the example, a model representing a slider inherits from an Observed class. The observed base class can add observers, remove them, and notify them. The notify method calls “update” on any of the slider’s observers (triggered by property setter methods). One observer just keeps track of the history while another prints out some HTML based on the slider’s value.

Observer pattern is widely used in GUI programming, also other event-processing architectures.

  • database triggers
  • Django’s signaling system
  • QT GUI app framework’s signals
  • many uses of WebSockets
31
Q

State Pattern

multiplexer example

A

Intended to provide objects whose behavior changes when their state changes - objects that have modes.

multiplexer example - two states.

when active, accepts connections - event name, callback pairs

for event_name, callback in ((“name”, func)):

__multiplexer.connect(event_name, callback)

__multiplexer.connect(event_name, gen_callback)

for multiplexer object we can use state-specific methods.

@state.setter

def state(self, state):

__if state == Multiplexer.ACTIVE:

____self.connect = # private methods

…more assignments

__else:

____self.connect = lambda *args: None #for each method you want to cancel.

32
Q

Strategy Pattern

A

Provides means of encapsulating a set of algorithms that can be used interchangeably, depending on the user’s needs.

class accepts an algorithm and calls that algorithm’s methods. The interchangeable algorithms will have methods with the same name or will become the original class’s method.

class Layout:

__def __init__(self, tabulator):

____self.tabulate = tabulator

tab = Layout(HtmlTab)

tab.tabulate(##things HtmlTab needs to have)

33
Q

Template Pattern

A

Allows us to define the steps of an algorithm but defer the execution of those steps to subclasses

A lot like the Bridge structural pattern

Example:

Make an AbstractWordCounter with two static methods - can_count(filename) and count(filename). Subclasses are made for text and html documents.

so we can do this:

def count_words(filename):

__for wordCounter in (TextCounter, HtmlCounter):

____if wordCounter.can_count(filename):

______return wordCounter.count(filename)

34
Q

Visitor Pattern

A

Apply a function to every item in a collection or aggregate object. Different from the iterator only in perspective - we are applying an external function on each item. This is done with map.

35
Q
  1. Patterns to use with coroutines
  2. Pattern for lazy evaluation
  3. Patterns with no direct support in Python
A
  1. Chain of responsibility, Mediator, Observer
  2. Command
  3. State, Strategy, Template