Python Design Pattern (Python Technologies)
Python Design Pattern (Python Technologies)
Intent/Motive
It describes what the pattern does.
Applicability
It describes the list of situations where pattern is applicable.
Why Python?
Python is an open source scripting language. It has libraries that
support a variety of design patterns. The syntax of python is easy to
understand and uses English keywords.
Python provides support for the list of design patterns that are
mentioned below. These design patterns will be used throughout this
tutorial −
Singleton pattern
Factory pattern
Builder Pattern
Prototype Pattern
Facade Pattern
Command Pattern
Adapter Pattern
Prototype Pattern
Decorator Pattern
Proxy Pattern
Observer Pattern
State Pattern
Strategy Pattern
Template Pattern
Flyweight Pattern
Interpreted
Python is processed at runtime using the interpreter. There is no
need to compile program before execution. It is similar to PERL and
PHP.
Object-Oriented
Python follows object-oriented style and design patterns. It includes
class definition with various features like encapsulation,
polymorphism and many more.
Portable
Python code written in Windows operating system and can be used in
Mac operating system. The code can be reused and portable as per
the requirements.
Easy to code
Python syntax is easy to understand and code. Any developer can
understand the syntax of Python within few hours. Python can be
described as “programmer-friendly”
Extensible
If needed, a user can write some of Python code in C language as
well. It is also possible to put python code in source code in different
languages like C++. This makes Python an extensible language.
Important Points
Consider the following important points related to Python
programming language −
https://www.python.org/downloads/
It includes packages for various operating systems like Windows,
MacOS and Linux distributions.
Python Strings
The basic declaration of strings is as follows −
Python Lists
The lists of python can be declared as compound data types
separated by commas and enclosed within square brackets ([]).
Python Tuples
A tuple is dynamic data type of Python, which consists of number of
values separated by commas. Tuples are enclosed with parentheses.
Python Dictionary
Python dictionary is a type of hash table. A dictionary key can be
almost any data type of Python. The data types are usually numbers
or strings.
Pattern Name
Intent
Aliases
Motivation
Problem
Solution
Structure
Participants
Constraints
Sample Code
Model View Controller Pattern
Model View Controller is the most commonly used design pattern.
Developers find it easy to implement this design pattern.
Model
It consists of pure application logic, which interacts with the database.
It includes all the information to represent data to the end user.
View
View represents the HTML files, which interact with the end user. It
represents the model’s data to user.
Controller
It acts as an intermediary between view and model. It listens to the
events triggered by view and queries model for the same.
Python code
Let us consider a basic object called “Person” and create an MVC
design pattern.
Model.py
import json
result = []
return result
It calls for a method, which fetches all the records of the Person table
in database. The records are presented in JSON format.
View
It displays all the records fetched within the model. View never
interacts with model; controller does this work (communicating with
model and view).
def startView():
def endView():
print 'Goodbye!'
Controller
Controller interacts with model through the getAll() method which
fetches all the records displayed to the end user.
import view
def showAll():
#calls view
def start():
view. startView()
input = raw_input()
if input == 'y' :
return showAll()
else :
if __name__ == "__main__" :
start()
Singleton
This pattern restricts the instantiation of a class to one object. It is a
type of creational pattern and involves only one class to create
methods and specified objects.
class Singleton :
__instance = None
@staticmethod
def getInstance():
Singleton ()
else :
s = Singleton ()
print s
s = Singleton . getInstance()
print s
s = Singleton . getInstance()
print s
Output
The above program generates the following output −
The number of instances created are same and there is no difference
in the objects listed in output.
Factory
The factory pattern comes under the creational patterns list category.
It provides one of the best ways to create an object. In factory
pattern, objects are created without exposing the logic to client and
referring to the newly created object using a common interface.
html = ""
html = "<img></img>"
html = "<input></input>"
class Flash ( Button ):
html = "<obj></obj>"
button_obj = ButtonFactory ()
for b in button:
The button class helps to create the html tags and the associated
html page. The client will not have access to the logic of code and the
output represents the creation of html page.
Output
Explanation
The python code includes the logic of html tags, which specified
value. The end user can have a look on the HTML file created by the
Python code.
Builder
Builder Pattern is a unique design pattern which helps in building
complex object using simple objects and uses an algorithmic
approach. This design pattern comes under the category of creational
pattern. In this design pattern, a builder class builds the final object in
step-by-step procedure. This builder is independent of other objects.
class Director :
__builder = None
# Then engine
i = 0
while i < 4 :
i += 1
return car
class Car :
class Builder :
wheel = Wheel ()
wheel. size = 22
return wheel
engine = Engine ()
return engine
body = Body ()
return body
# Car parts
class Wheel :
size = None
class Engine :
horsepower = None
class Body :
shape = None
def main():
jeepBuilder = JeepBuilder () # initializing the
class
director = Director ()
# Build Jeep
print "Jeep"
jeep. specification()
print ""
if __name__ == "__main__" :
main()
Output
The above program generates the following output −
Prototype
Prototype design pattern helps to hide the complexity of the instances
created by the class. The concept of the existing object will differ with
that of the new object, which is created from scratch.
The newly copied object may have some changes in the properties if
required. This approach saves time and resources that go in for the
development of a product.
import copy
class Prototype :
_type = None
_value = None
pass
class ObjectFactory :
"""
__type1Value1 = None
__type1Value2 = None
__type2Value1 = None
__type2Value2 = None
@staticmethod
def initialize():
@staticmethod
def getType1Value1():
@staticmethod
def getType1Value2():
@staticmethod
def getType2Value1():
@staticmethod
def getType2Value2():
def main():
ObjectFactory . initialize()
if __name__ == "__main__" :
main()
Output
The above program will generate the following output −
The output helps in creating new objects with the existing ones and it
is clearly visible in the output mentioned above.
Facade
Facade design pattern provides a unified interface to a set of
interfaces in a subsystem. It defines a higher-level interface that any
subsystem can use.
@staticmethod
def produce_spark():
return True
self . revs_per_minute = 0
self . revs_per_minute = 0
class _FuelTank ( object ):
@property
@level . setter
@property
if self . _is_on:
else :
pass
pass
# Facade
@property
return 17.0
print ( "\nStarting..." )
self . dashboard. show()
else :
litres_needed = km / km_per_litre
return True
else :
return False
print ( "\n" )
else :
print ( "\nParking..." )
def main():
car = Car ()
car. start()
car. drive()
car. park()
car. fill_up_tank()
car. drive()
car. start()
car. drive()
if __name__ == "__main__" :
main()
Output
The above program generates the following output −
Explanation
This program is designed with a scenario. It is that of starting the
engine of a car or any driving vehicle. If you observe the code, it
includes the associated functions to drive, to park and to consume
fuel as well.
Command
Command Pattern adds a level of abstraction between actions and
includes an object, which invokes these actions.
print 'b:' , b
print 'c:' , c
class Command :
print cmd()
cmd( 3 )
Output
The above program generates the following output −
Explanation
The output implements all the commands and keywords listed in
Python language. It prints the necessary values of the variables.
Adapter
Adapter pattern works as a bridge between two incompatible
interfaces. This type of design pattern comes under structural pattern
as this pattern combines the capability of two independent interfaces.
# Adaptee
return 230
return 1
return - 1
return 0
# Target interface
class USASocketInterface :
# The Adapter
__socket = None
return 110
# Client
class ElectricKettle :
__power = None
else :
else :
def main():
# Plug in
socket = Socket ()
# Make coffee
kettle. boil()
return 0
if __name__ == "__main__" :
main()
Output
The above program generates the following output −
Explanation
The code includes adapter interface with various parameters and
attributes. It includes Adaptee along with Target interface that
implements all the attributes and displays the output as visible.
Decorator
Decorator pattern allows a user to add new functionality to an existing
object without altering its structure. This type of design pattern comes
under structural pattern as this pattern acts as a wrapper to existing
class.
This pattern creates a decorator class, which wraps the original class
and provides additional functionality keeping the class methods
signature intact.
import six
pass
return 1.00
return 'coffee'
import coffeeshop
Output
The above program generates the following output −
Proxy
The proxy design pattern includes a new object, which is called
“Proxy” in place of an existing object which is called the “Real
Subject”. The proxy object created of the real subject must be on the
same interface in such a way that the client should not get any idea
that proxy is used in place of the real object. Requests generated by
the client to the proxy are passed through the real subject.
class Image :
class Proxy :
self . _proxystate = 1
Output
The above program generates the following output −
PDF = 0
TEXT = 1
else :
print '<html>'
' % line
print '</html>'
class TextHandler ( Handler ):
else :
print line
if __name__ == '__main__' :
pdf_handler = PDFHandler ()
text_handler = TextHandler ()
Output
The above program generates the following output −
Explanation
The above code creates a report for monthly tasks where it sends
commands through each function. It takes two handlers – for PDF
and for text. It prints the output once the required object executes
each function.
Observer
In this pattern, objects are represented as observers that wait for an
event to trigger. An observer attaches to the subject once the
specified event occurs. As the event occurs, the subject tells the
observers that it has occurred.
import threading
import time
import pdb
class Downloader ( threading. Thread ):
print 'downloading'
for i in range( 1 , 5 ):
self . i = i
time. sleep( 2 )
print 'unfunf'
for i in range( 1 , 5 ):
time. sleep( 1 )
t. join ()
print 'done'
t = Downloader ()
t. start()
time. sleep( 1 )
t1 = Worker ()
t1. start()
t2 = Worker ()
t2. start()
t3 = Worker ()
t3. start()
Output
The above program generates the following output −
Explanation
The above code explains the procedure of downloading a particular
result. As per the observer pattern logic, every object is treated as
observer. It prints the output when event is triggered.
State
It provides a module for state machines, which are implemented
using subclasses, derived from a specified state machine class. The
methods are state independent and cause transitions declared using
decorators.
name = "state"
allowed = []
else :
name = "off"
allowed = [ 'on' ]
class On ( ComputerState ):
name = "on"
name = "suspend"
allowed = [ 'on' ]
name = "hibernate"
allowed = [ 'on' ]
if __name__ == "__main__" :
comp = Computer ()
comp. change( On )
comp. change( On )
comp. change( On )
Output
The above program generates the following output −
Strategy
The strategy pattern is a type of behavioral pattern. The main goal of
strategy pattern is to enable client to choose from different algorithms
or procedures to complete the specified task. Different algorithms can
be swapped in and out without any complications for the mentioned
task.
import types
class StrategyExample :
if __name__ == '__main__' :
strat0 = StrategyExample ()
strat0. execute()
strat1. execute()
strat2. execute()
Output
The above program generates the following output −
Explanation
It provides a list of strategies from the functions, which execute the
output. The major focus of this behavior pattern is behavior.
Template
A template pattern defines a basic algorithm in a base class using
abstract operation where subclasses override the concrete behavior.
The template pattern keeps the outline of algorithm in a separate
method. This method is referred as the template method.
class MakeMeal :
self . prepare()
self . cook()
self . eat()
makePizza = MakePizza ()
makePizza. go()
print 25 * "+"
makeTea = MakeTea ()
makeTea. go()
Output
The above program generates the following output −
Explanation
This code creates a template to prepare meal. Here, each parameter
represents the attribute to create a part of meal like tea, pizza, etc.
pass
return "ComplexPatter[%s]TooHugeinSize" % (
gene_code)
family = {}
try :
return id
cg = ComplexGenetics ()
def test():
family_objects = []
for i in data:
obj = Families ( i[ 0 ], i[ 1 ])
obj. set_genetic_info( i[ 2 ])
for i in family_objects:
print "id = " + str( id( i))
print i. get_genetic_info()
if __name__ == '__main__' :
test()
Output
The above program generates the following output −
Abstract Factory
The abstract factory pattern is also called factory of factories. This
design pattern comes under the creational design pattern category. It
provides one of the best ways to create an object.
class Window :
__toolkit = ""
__purpose = ""
class UIFactory :
def getToolboxWindow( self ): pass
return GtkToolboxWindow ()
return GtkLayersWindow ()
return GtkMainWindow ()
return QtToolboxWindow ()
return QtLayersWindow ()
return QtMainWindow ()
if __name__ == "__main__" :
gnome = True
ui = GtkUIFactory ()
elif kde:
ui = QtUIFactory ()
Output
The above program generates the following output −
Explanation
In the above program, the abstract factory creates objects for each
window. It calls for each method, which executes the output as
expected.
Object Oriented
The object oriented pattern is the most commonly used pattern. This
pattern can be found in almost every programming language.
class Parrot :
# class attribute
species = "bird"
# instance attribute
Output
The above program generates the following output
Explanation
The code includes class attribute and instance attributes, which are
printed as per the requirement of the output. There are various
features that form part of the object oriented pattern. The features are
explained in the next chapter.
Object Oriented Concepts Implementation
In this chapter, we will focus on patterns using object oriented
concepts and its implementation in Python. When we design our
programs around blocks of statements, which manipulate the data
around functions, it is called procedure-oriented programming. In
object-oriented programming, there are two main instances called
classes and objects.
class Robot :
population = 0
Robot . population += 1
Robot . population -= 1
if Robot . population == 0 :
print ( "{} was the last one." . format( self .
name))
else :
Robot . population))
@classmethod
droid1. say_hi()
Robot . how_many()
droid2. say_hi()
Robot . how_many()
droid1. die ()
droid2. die ()
Robot . how_many()
Output
The above program generates the following output −
Explanation
This illustration helps to demonstrate the nature of class and object
variables.
import time
def fib():
a, b = 0 , 1
while True :
yield b
a, b = b, a + b
g = fib()
try :
for e in g:
print ( e)
time. sleep( 1 )
except KeyboardInterrupt :
If you focus on the pattern, Fibonacci series is printed with the iterator
pattern. On forceful termination of user, the following output is printed
−
Explanation
This python code follows the iterator pattern. Here, the increment
operators are used to start the count. The count ends on forceful
termination by the user.
Dictionaries
Dictionaries are the data structures, which include a key value
combination. These are widely used in place of JSON – JavaScript
Object Notation. Dictionaries are used for API (Application
Programming Interface) programming. A dictionary maps a set of
objects to another set of objects. Dictionaries are mutable; this
means they can be changed as and when needed based on the
requirements.
d = dict() # or d = {}
d[ 'xyz' ] = 123
d[ 'abc' ] = 345
print ( d)
print ( d. keys())
print ( d. values())
# iterate over dictionary
for i in d :
del d[ 'xyz' ]
# check again
print ( "xyz" in d)
Output
The above program generates the following output −
Note − There are drawbacks related to the implementation of
dictionaries in Python.
Drawback
Dictionaries do not support the sequence operation of the sequence
data types like strings, tuples and lists. These belong to the built-in
mapping type.
Lists Data Structure
The Lists data structure is a versatile datatype in Python, which can
be written as a list of comma separated values between square
brackets.
Syntax
Here is the basic syntax for the structure −
List_name = [ elements ];
If you observe, the syntax is declared like arrays with the only
difference that lists can include elements with different data types.
The arrays include elements of the same data type. A list can contain
a combination of strings, integers and objects. Lists can be used for
the implementation of stacks and queues.
# Output: p
print ( my_list[ 0 ])
# Output: o
print ( my_list[ 2 ])
# Output: e
print ( my_list[ 4 ])
# my_list[4.0]
# Nested List
n_list = [ "Happy" , [ 2 , 0 , 1 , 5 ]]
# Nested indexing
# Output: a
print ( n_list[ 0 ][ 1 ])
# Output: 5
print ( n_list[ 1 ][ 3 ])
Output
The above program generates the following output −
# Set in Python
set1 = set ()
set2 = set ()
for i in range( 1 , 6 ):
set1. add ( i)
for i in range( 3 , 8 ):
set2. add ( i)
print ( "\n" )
print ( "\n" )
print ( "\n" )
# difference between set3 and set4
print ( "\n" )
set5. clear()
Output
The above program generates the following output −
The frozen set can be demonstrated using the following program −
print ( normal_set)
# A frozen set
print ( frozen_set)
Output
The above program generates the following output −
Queues
Queue is a collection of objects, which define a simple data structure
following the FIFO (Fast In Fast Out) and the LIFO (Last In First Out)
procedures. The insert and delete operations are referred
as enqueue and dequeue operations.
import Queue
q = Queue . Queue ()
for x in range( 4 ):
print q. get ()
Output
The above program generates the following output −
How to implement the LIFO procedure?
The following program helps in the implementation of the LIFO
procedure −
import Queue
q = Queue . LifoQueue ()
for x in range( 4 ):
print q. get ()
Output
The above program generates the following output −
What is a Priority Queue?
Priority queue is a container data structure that manages a set of
records with the ordered keys to provide quick access to the record
with smallest or largest key in specified data structure.
import Queue
q = Queue . PriorityQueue ()
q. put( Task ( 100 , 'a not agent task' ) )
cur_task = q. get ()
Output
The above program generates the following output −
Strings and Serialization
String serialization is the process of writing a state of object into a
byte stream. In python, the “pickle” library is used for enabling
serialization. This module includes a powerful algorithm for serializing
and de-serializing a Python object structure. “Pickling” is the process
of converting Python object hierarchy into byte stream and
“unpickling” is the reverse procedure.
import pickle
print ( serial_grades)
print ( received_grades)
Output
The above program generates the following output −
Concurrency in Python
Concurrency is often misunderstood as parallelism. Concurrency
implies scheduling independent code to be executed in a systematic
manner. This chapter focuses on the execution of concurrency for an
operating system using Python.
import os
import time
import threading
import multiprocessing
NUM_WORKERS = 4
def only_sleep():
os. getpid(),
time. sleep( 1 )
def crunch_numbers():
print ( "PID: %s, Process Name: %s, Thread Name:
%s" % (
os. getpid(),
x = 0
x += 1
only_sleep()
Output
The above program generates the following output −
Explanation
“multiprocessing” is a package similar to the threading module. This
package supports local and remote concurrency. Due to this module,
programmers get the advantage to use multiple processes on the
given system.
Anti
Anti-patterns follow a strategy in opposition to predefined design
patterns. The strategy includes common approaches to common
problems, which can be formalized and can be generally considered
as a good development practice. Usually, anti-patterns are opposite
and undesirable. Anti- patterns are certain patterns used in software
development, which are considered as bad programming practices.
Correctness
These patterns literally break your code and make you do wrong
things. Following is a simple illustration of this −
r = Rectangle ( 5 , 6 )
Maintainability
A program is said to be maintainable if it is easy to understand and
modify as per the requirement. Importing module can be considered
as an example of maintainability.
import math
x = math.ceil(y)
# or
import multiprocessing as mp
pool = mp.pool(8)
Example of anti-pattern
Following example helps in the demonstration of anti-patterns −
#Bad
return None
return r
#continue processing
pass
#Good
def filter_for_foo( l):
return r
try :
#continue processing
except SomeException :
i = 0
while i < 10 :
do_something()
Explanation
The example includes the demonstration of good and bad standards
for creating a function in Python.
Exception Handling
Handling exceptions is also a primary criterion of design patterns. An
exception is an error that happens during the execution of a program.
When a particular error occurs, it is important to generate an
exception. This helps in curbing program crashes.
randomList = [ 'a' , 0 , 2 ]
try :
r = 1 / int ( entry)
break
except :
print ()
print ( "The reciprocal of" , entry, "is" , r)
Output
The above program generates the following output −
Raising Exceptions
In Python programming specifically, exceptions are raised when
corresponding error of code occurs at run time. This can be forcefully
raised using the “raise” keyword.
Syntax
raise KeyboardInterrupt
...
KeyboardInterrupt