discover · compare · collections · requirements · contribute · feed · watching · stats · help with your tokens
faif/python-patterns · source
Snapshot 0 · 2026-11-04T12:47:22Z · Python ·
Content fingerprint
882c60181a8d95560897806fb0328b1447d378efd2f0f1bf57651b62091930baGitHub description at capture
A collection of design patterns/idioms in Python
README at capture
# python-patterns
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.
## Creational Patterns
> Patterns that deal with **object creation** — abstracting and controlling how instances are made.
```mermaid
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](patterns/creational/abstract_factory.py) | use a generic function with specific factories |
| [borg](patterns/creational/borg.py) | a singleton with shared-state among instances |
| [builder](patterns/creational/builder.py) | instead of using multiple constructors, builder object receives parameters and returns constructed objects |
| [factory](patterns/creational/factory.py) | delegate a specialized function/method to create instances |
| [lazy_evaluation](patterns/creational/lazy_evaluation.py) | lazily-evaluated property pattern in Python |
| [pool](patterns/creational/pool.py) | preinstantiate and maintain a group of instances of the same type |
| [prototype](patterns/creational/prototype.py) | use a factory and clones of a prototype for new instances (if instantiation is expensive) |
## Structural Patterns
> Patterns that define **how classes and objects are composed** to form larger, flexible structures.
```mermaid
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](patterns/structural/3-tier.py) | data<->business logic<->presentation separation (strict relationships) |
| [adapter](patterns/structural/adapter.py) | adapt one interface to another using a white-list |
| [bridge](patterns/structural/bridge.py) | a client-provider middleman to soften interface changes |
| [composite](patterns/structural/composite.py) | lets clients treat individual objects and compositions uniformly |
| [decorator](patterns/structural/decorator.py) | wrap functionality with other functionality in order to affect outputs |
| [facade](patterns/structural/facade.py) | use one class as an API to a number of others |
| [flyweight](patterns/structural/flyweight.py) | transparently reuse existing instances of objects with similar/identical state |
| [front_controller](patterns/structural/front_controller.py) | single handler requests coming to the application |
| [mvc](patterns/structural/mvc.py) | model<->view<->controller (non-strict relationships) |
| [proxy](patterns/structural/proxy.py) | an object funnels operations to something else |
## Behavioral Patterns
> Patterns concerned with **communication and responsibility** between objects.
```mermaid
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](patterns/behavioral/chain_of_responsibility.py) | apply a chain of successive handlers to try and process the data |
| [catalog](patterns/behavioral/catalog.py) | general methods will call different specialized methods based on construction parameter |
| [chaining_method](patterns/behavioral/chaining_method.py) | continue callback next object method |
| [command](patterns/behavioral/command.py) | bundle a command and arguments to call later |
| [interpreter](patterns/behavioral/interpreter.py) | define a grammar for a language and use it to interpret statements |
| [iterator](patterns/behavioral/iterator.py) | traverse a container and access the container's elements |
| [iterator](patterns/behavioral/iterator_alt.py) (alt. impl.) | traverse a container and access the container's elements |
| [mediator](patterns/behavioral/mediator.py) | an object that knows how to connect other objects and act as a proxy |
| [memento](patterns/behavioral/memento.py) | generate an opaque token that can be used to go back to a previous state |
| [observer](patterns/behavioral/observer.py) | provide a callback for notification of events/changes to data |
| [publish_subscribe](patterns/behavioral/publish_subscribe.py) | a source syndicates events/data to 0+ registered listeners |
| [registry](patterns/behavioral/registry.py) | keep track of all subclasses of a given class |
| [servant](patterns/behavioral/servant.py) | provide common functionality to a group of classes without using inheritance |
| [specification](patterns/behavioral/specification.py) | business rules can be recombined by chaining the business rules together using boolean logic |
| [state](patterns/behavioral/state.py) | logic is organized into a discrete number of potential states and the next state that can be transitioned to |
| [strategy](patterns/behavioral/strategy.py) | selectable operations over the same data |
| [template](patterns/behavioral/template.py) | an object imposes a structure but takes pluggable components |
| [visitor](patterns/behavioral/visitor.py) | invoke a callback for all items of a collection |
## Design for Testability Patterns
| Pattern | Description |
|:--------------------------------------------------------:|------------------------------------|
| [dependency_injection](patterns/dependency_injection.py) | 3 variants of dependency injection |
## Fundamental Patterns
| Pattern | Description |
|:----------------------------------------------------------------:|-----------------------------------------------------------------------------|
| [delegation_pattern](patterns/fundamental/delegation_pattern.py) | an object handles a request by delegating to a second object (the delegate) |
## Others
| Pattern | Description |
|:----------------------------------------------:|--------------------------------------------------------------------------------------------------------------------------|
| [blackboard](patterns/other/blackboard.py) | architectural model, assemble different sub-system knowledge to build a solution, AI approach - non gang of four pattern |
| [graph_search](patterns/other/graph_search.py) | graphing algorithms - non gang of four pattern |
| [hsm](patterns/other/hsm/hsm.py) | hierarchical state machine - non gang of four pattern |
## 🚫 Anti-Patterns
This section lists some common design patterns that are **not recommended** in Python and explains why.
### 🧱 Singleton
**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.
### 🌀 God Object
**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.
### 🔁 Inheritance overuse
**Why not:**
- Deep inheritance trees make code brittle.
- Prefer composition and delegation.
- “Favor composition over inheritance.”
## Videos
* [Design Patterns in Python by Peter Ullrich](https://www.youtube.com/watch?v=bsyjSW46TDg)
* [Sebastian Buczyński - Why you don't need design patterns in Python?](https://www.youtube.com/watch?v=G5OeYHCJuv0)
* [You Don't Need That!](https://www.youtube.com/watch?v=imW-trt0i9I)
* [Pluggable Libs Through Design Patterns](https://www.youtube.com/watch?v=PfgEU3W0kyU)
## Contributing
When an implementation is added or modified, please review the following guidelines:
##### Docstrings
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](patterns/structural/facade.py) has a good example of detailed description, but sometimes the shorter one as in [template.py](patterns/behavioral/template.py) would suffice.
##### Python 2 compatibility
To see Python 2 compatible versions of some patterns please check-out the [legacy](https://github.com/faif/python-patterns/tree/legacy) tag.
##### Update README
When everything else is done - update corresponding part of README.
##### Travis CI
Please run the following before submitting a patch:
- If you have a bash-compatible shell, use `./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.
## Contributing via issue triage [](https://www.codetriage.com/faif/python-patterns)
You can triage issues and pull requests on [CodeTriage](https://www.codetriage.com/faif/python-patterns).