faif/ python-patterns
View on GitHubA collection of design patterns/idioms in Python
A collection of design patterns/idioms in Python
A collection of design patterns and idioms in Python.
Remember that each pattern has its own trade-offs. And you need to pay attention more to why you're choosing a certain pattern than to how to implement it.
Patterns that deal with object creation — abstracting and controlling how instances are made.
graph LR
Client -->|requests object| AbstractFactory
AbstractFactory -->|delegates to| ConcreteFactory
ConcreteFactory -->|produces| Product
Builder -->|step-by-step| Director
Director -->|returns| BuiltObject
FactoryMethod -->|subclass decides| ConcreteProduct
Pool -->|reuses| PooledInstance
| Pattern | Description | |:-------:| ----------- | | abstract_factory | use a generic function with specific factories | | borg | a singleton with shared-state among instances | | builder | instead of using multiple constructors, builder object receives parameters and returns constructed objects | | factory | delegate a specialized function/method to create instances | | lazy_evaluation | lazily-evaluated property pattern in Python | | pool | preinstantiate and maintain a group of instances of the same type | | prototype | use a factory and clones of a prototype for new instances (if instantiation is expensive) |
Patterns that define how classes and objects are composed to form larger, flexible structures.
graph TD
Client --> Facade
Facade --> SubsystemA
Facade --> SubsystemB
Facade --> SubsystemC
Client2 --> Adapter
Adapter --> LegacyService
Client3 --> Proxy
Proxy -->|controls access to| RealSubject
Component --> Composite
Composite --> Leaf1
Composite --> Leaf2
| Pattern | Description | |:-----------------------------------------------------------:|--------------------------------------------------------------------------------| | 3-tier | data<->business logic<->presentation separation (strict relationships) | | adapter | adapt one interface to another using a white-list | | bridge | a client-provider middleman to soften interface changes | | composite | lets clients treat individual objects and compositions uniformly | | decorator | wrap functionality with other functionality in order to affect outputs | | facade | use one class as an API to a number of others | | flyweight | transparently reuse existing instances of objects with similar/identical state | | front_controller | single handler requests coming to the application | | mvc | model<->view<->controller (non-strict relationships) | | proxy | an object funnels operations to something else |
Patterns concerned with communication and responsibility between objects.
graph LR
Sender -->|sends event| Observer1
Sender -->|sends event| Observer2
Request --> Handler1
Handler1 -->|passes if unhandled| Handler2
Handler2 -->|passes if unhandled| Handler3
Context -->|delegates to| Strategy
Strategy -->|executes| Algorithm
Originator -->|saves state to| Memento
Caretaker -->|holds| Memento
| Pattern | Description | |:-------------------------------------------------------------------------:|--------------------------------------------------------------------------------------------------------------| | chain_of_responsibility | apply a chain of successive handlers to try and process the data | | catalog | general methods will call different specialized methods based on construction parameter | | chaining_method | continue callback next object method | | command | bundle a command and arguments to call later | | interpreter | define a grammar for a language and use it to interpret statements | | iterator | traverse a container and access the container's elements | | iterator (alt. impl.) | traverse a container and access the container's elements | | mediator | an object that knows how to connect other objects and act as a proxy | | memento | generate an opaque token that can be used to go back to a previous state | | observer | provide a callback for notification of events/changes to data | | publish_subscribe | a source syndicates events/data to 0+ registered listeners | | registry | keep track of all subclasses of a given class | | servant | provide common functionality to a group of classes without using inheritance | | specification | business rules can be recombined by chaining the business rules together using boolean logic | | state | logic is organized into a discrete number of potential states and the next state that can be transitioned to | | strategy | selectable operations over the same data | | template | an object imposes a structure but takes pluggable components | | visitor | invoke a callback for all items of a collection |
| Pattern | Description | |:--------------------------------------------------------:|------------------------------------| | dependency_injection | 3 variants of dependency injection |
| Pattern | Description | |:----------------------------------------------------------------:|-----------------------------------------------------------------------------| | delegation_pattern | an object handles a request by delegating to a second object (the delegate) |
| Pattern | Description | |:----------------------------------------------:|--------------------------------------------------------------------------------------------------------------------------| | blackboard | architectural model, assemble different sub-system knowledge to build a solution, AI approach - non gang of four pattern | | graph_search | graphing algorithms - non gang of four pattern | | hsm | hierarchical state machine - non gang of four pattern |
This section lists some common design patterns that are not recommended in Python and explains why.
Why not:
Why not:
Why not:
When an implementation is added or modified, please review the following guidelines:
Add module level description in form of a docstring with links to corresponding references or other useful information. Add "Examples in Python ecosystem" section if you know some. It shows how patterns could be applied to real-world problems. facade.py has a good example of detailed description, but sometimes the shorter one as in template.py would suffice.
To see Python 2 compatible versions of some patterns please check-out the legacy tag.
When everything else is done - update corresponding part of README.
Please run the following before submitting a patch:
./lint.sh to run formatting,
linting, type checking, and tests.Development dependencies are pinned in Pipfile.lock. After changing
Pipfile, activate a Python 3.10 virtual environment and run make lock to
regenerate it.
You can triage issues and pull requests on CodeTriage.
No comments yet. Set the tone — say what you would want to know.