0

faif/python-patterns

View on GitHub

A collection of design patterns/idioms in Python

42,9566,991Pythondesign-patternsidiomspythonUpdated 13d ago
README

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.

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) |

Structural Patterns

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 |

Behavioral Patterns

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 |

Design for Testability Patterns

| Pattern | Description | |:--------------------------------------------------------:|------------------------------------| | dependency_injection | 3 variants of dependency injection |

Fundamental Patterns

| Pattern | Description | |:----------------------------------------------------------------:|-----------------------------------------------------------------------------| | delegation_pattern | an object handles a request by delegating to a second object (the delegate) |

Others

| 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 |

🚫 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

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 has a good example of detailed description, but sometimes the shorter one as in template.py would suffice.

Python 2 compatibility

To see Python 2 compatible versions of some patterns please check-out the 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 Open Source Helpers

You can triage issues and pull requests on CodeTriage.

Comments0

No comments yet. Set the tone — say what you would want to know.