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:
- Python modules are already singletons — every module is imported only once.
- Explicit singleton classes add unnecessary complexity.
- Better alternatives: use module-level variables or dependency injection.
Why not:
- Centralizes too much logic in a single class.
- Makes code harder to test and maintain.
- Better alternative: split functionality into smaller, cohesive classes.
Why not:
- Deep inheritance trees make code brittle.
- Prefer composition and delegation.
- “Favor composition over inheritance.”
- Design Patterns in Python by Peter Ullrich
- Sebastian Buczyński - Why you don't need design patterns in Python?
- You Don't Need That!
- Pluggable Libs Through Design Patterns
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:
black .This lints your code.- Either
toxortox -e ci37for unit tests. - If you have a bash compatible shell, use
./lint.sh.
You can triage issues and pull requests on CodeTriage.