Convert Figma logo to code with AI

faif logopython-patterns

A collection of design patterns/idioms in Python

42,839
7,008
42,839
15

Top Related Projects

An ultra-simplified explanation to design patterns

Learn how to design large-scale systems. Prep for the system design interview. Includes Anki flashcards.

Design patterns implemented in Java

A curated list of software and architecture related design patterns.

Everything you need to know to get the job.

📝 Algorithms and data structures implemented in JavaScript with explanations and links to further readings

Quick Overview

The python-patterns repository on GitHub is a collection of design patterns and idioms in Python. It provides a comprehensive overview of various design patterns and their implementation in the Python programming language. The repository serves as a valuable resource for developers looking to enhance their understanding and application of design patterns in their Python projects.

Pros

  • Comprehensive Coverage: The repository covers a wide range of design patterns, including Creational, Structural, and Behavioral patterns, providing a thorough exploration of these concepts in the context of Python.
  • Practical Examples: Each design pattern is accompanied by clear and concise code examples, making it easier for developers to understand the practical application of these patterns.
  • Active Community: The project has an active community of contributors, ensuring regular updates and improvements to the content.
  • Educational Resource: The repository can be an excellent learning resource for developers, especially those new to design patterns or Python, as it offers a structured and organized way to explore these concepts.

Cons

  • Lack of Detailed Explanations: While the code examples are helpful, the repository could benefit from more detailed explanations and discussions of the design patterns, their use cases, and their trade-offs.
  • Uneven Quality: The quality and depth of the examples may vary across different design patterns, as the repository is a community-driven project.
  • Potential Outdated Content: As with any community-driven project, there is a risk of some content becoming outdated over time, especially with the rapid evolution of Python and its ecosystem.
  • Limited Practical Guidance: The repository focuses more on the theoretical aspects of design patterns and their implementation, and may lack practical guidance on how to apply them in real-world scenarios.

Code Examples

Here are a few code examples from the python-patterns repository:

Singleton Pattern

The Singleton pattern ensures that a class has only one instance and provides a global point of access to it.

class Singleton(object):
    _instance = None

    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = super(Singleton, cls).__new__(cls)
        return cls._instance

Factory Method Pattern

The Factory Method pattern defines an interface for creating an object, but lets subclasses decide which class to instantiate.

class Pizza:
    def __init__(self, name):
        self.name = name

    def __str__(self):
        return self.name

class CheesePizza(Pizza):
    def __init__(self):
        super().__init__("Cheese Pizza")

class VeggiePizza(Pizza):
    def __init__(self):
        super().__init__("Veggie Pizza")

class PizzaFactory:
    @staticmethod
    def create_pizza(pizza_type):
        if pizza_type == "cheese":
            return CheesePizza()
        elif pizza_type == "veggie":
            return VeggiePizza()
        else:
            raise ValueError("Invalid pizza type")

Observer Pattern

The Observer pattern defines a one-to-many dependency between objects, so that when one object changes state, all its dependents are notified and updated automatically.

class Subject:
    def __init__(self):
        self._observers = []

    def attach(self, observer):
        self._observers.append(observer)

    def detach(self, observer):
        self._observers.remove(observer)

    def notify(self):
        for observer in self._observers:
            observer.update(self)

class ConcreteSubject(Subject):
    def __init__(self, initial_state):
        super().__init__()
        self._state = initial_state

    @property
    def state(self):
        return self._state

    @state.setter
    def state(self, value):
        self._state = value
        self.notify()

class Observer:
    def update(self, subject):
        print(f"Observed state change: {subject.state}")

Getting Started

To get started with the python-patterns repository, follow these steps:

  1. Clone the repository to your local machine:

    git clone https://github.com/faif/python-patterns.git
    
  2. Navigate to the project directory:

Competitor Comparisons

An ultra-simplified explanation to design patterns

Error generating comparison

Learn how to design large-scale systems. Prep for the system design interview. Includes Anki flashcards.

Pros of system-design-primer

  • Comprehensive coverage of system design concepts and principles
  • Includes interactive diagrams and visual aids for better understanding
  • Provides real-world examples and case studies of large-scale systems

Cons of system-design-primer

  • Focuses on high-level system design rather than specific programming patterns
  • May be overwhelming for beginners due to its extensive content
  • Less hands-on coding examples compared to python-patterns

Code comparison

While a direct code comparison isn't particularly relevant due to the different focus of these repositories, here's a brief example of how they differ in approach:

python-patterns (Strategy pattern):

class Strategy:
    def __init__(self, func=None):
        self.name = "Default Strategy"
        if func:
            self.execute = func

    def execute(self):
        print(f"{self.name} is used!")

system-design-primer (System design example):

Client -> DNS -> Load Balancer -> Web Server -> Application Server -> Database

The python-patterns repository focuses on implementing design patterns in Python, while system-design-primer provides high-level system architecture diagrams and explanations.

Design patterns implemented in Java

Pros of java-design-patterns

  • More comprehensive, covering a wider range of design patterns
  • Better organized with clear categorization and documentation
  • Includes real-world examples and use cases for each pattern

Cons of java-design-patterns

  • Larger codebase, potentially overwhelming for beginners
  • Java-specific implementations may not translate easily to other languages
  • More complex project structure due to its size and scope

Code Comparison

python-patterns (Strategy pattern):

class Strategy:
    def __init__(self, function=None):
        self.name = "Default Strategy"
        if function:
            self.execute = function

    def execute(self):
        print(f"{self.name} is used!")

java-design-patterns (Strategy pattern):

public interface Strategy {
    int doOperation(int num1, int num2);
}

public class OperationAdd implements Strategy {
    @Override
    public int doOperation(int num1, int num2) {
        return num1 + num2;
    }
}

Summary

Both repositories offer valuable resources for learning design patterns. python-patterns is more concise and Python-focused, making it easier for Python developers to grasp quickly. java-design-patterns provides a more extensive collection of patterns with detailed explanations and examples, but its Java-centric approach may require adaptation for use in other languages.

A curated list of software and architecture related design patterns.

Pros of awesome-design-patterns

  • Covers a wide range of programming languages and design patterns
  • Includes links to external resources and articles for deeper learning
  • Provides a curated list of high-quality design pattern implementations

Cons of awesome-design-patterns

  • Lacks detailed explanations or code examples within the repository
  • May be overwhelming for beginners due to the large amount of information

Code comparison

python-patterns provides concrete Python implementations:

class Singleton:
    __instance = None
    def __new__(cls):
        if cls.__instance is None:
            cls.__instance = super().__new__(cls)
        return cls.__instance

awesome-design-patterns doesn't include code examples directly, but links to external resources:

- [Singleton](https://en.wikipedia.org/wiki/Singleton_pattern)
  - [Python Singleton](https://github.com/faif/python-patterns/blob/master/patterns/creational/singleton.py)

Summary

python-patterns focuses on Python-specific implementations with detailed explanations, while awesome-design-patterns offers a broader overview of design patterns across multiple languages. python-patterns is more suitable for Python developers looking for practical examples, whereas awesome-design-patterns serves as a comprehensive reference guide for various programming languages and paradigms.

Everything you need to know to get the job.

Pros of interviews

  • Covers a broader range of topics including algorithms, data structures, and system design
  • Includes solutions in multiple programming languages (Java, Python, C++)
  • Provides a comprehensive resource for technical interview preparation

Cons of interviews

  • Less focused on specific design patterns compared to python-patterns
  • May not provide as in-depth explanations for each pattern or concept
  • Could be overwhelming for beginners due to the large amount of content

Code Comparison

python-patterns (Strategy Pattern):

class Strategy:
    def __init__(self, function=None):
        self.name = "Default Strategy"
        if function:
            self.execute = function

    def execute(self):
        print(f"{self.name} is used!")

interviews (Binary Search Tree):

public class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}

Both repositories provide valuable resources for developers, but they serve different purposes. python-patterns focuses on implementing design patterns in Python, while interviews covers a wider range of topics for technical interview preparation across multiple languages.

📝 Algorithms and data structures implemented in JavaScript with explanations and links to further readings

Pros of javascript-algorithms

  • Extensive collection of algorithms and data structures
  • Well-organized with detailed explanations and complexity analysis
  • Includes unit tests for each implementation

Cons of javascript-algorithms

  • Focused solely on algorithms, lacking design patterns
  • May be overwhelming for beginners due to its comprehensive nature

Code Comparison

python-patterns (Strategy Pattern):

class Strategy:
    def __init__(self, func=None):
        self.name = "Default Strategy"
        if func:
            self.execute = func

    def execute(self):
        print(f"{self.name} is used!")

javascript-algorithms (Binary Search):

function binarySearch(sortedArray, seekElement) {
  let startIndex = 0;
  let endIndex = sortedArray.length - 1;

  while (startIndex <= endIndex) {
    const middleIndex = startIndex + Math.floor((endIndex - startIndex) / 2);
    // ... (implementation continues)
  }
}

Summary

While python-patterns focuses on design patterns in Python, javascript-algorithms provides a comprehensive collection of algorithms and data structures in JavaScript. The latter offers more depth in terms of algorithmic implementations but lacks coverage of design patterns. python-patterns is more suitable for learning software design principles, while javascript-algorithms is better for studying specific algorithms and their implementations.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

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
PatternDescription
abstract_factoryuse a generic function with specific factories
borga singleton with shared-state among instances
builderinstead of using multiple constructors, builder object receives parameters and returns constructed objects
factorydelegate a specialized function/method to create instances
lazy_evaluationlazily-evaluated property pattern in Python
poolpreinstantiate and maintain a group of instances of the same type
prototypeuse 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
PatternDescription
3-tierdata<->business logic<->presentation separation (strict relationships)
adapteradapt one interface to another using a white-list
bridgea client-provider middleman to soften interface changes
compositelets clients treat individual objects and compositions uniformly
decoratorwrap functionality with other functionality in order to affect outputs
facadeuse one class as an API to a number of others
flyweighttransparently reuse existing instances of objects with similar/identical state
front_controllersingle handler requests coming to the application
mvcmodel<->view<->controller (non-strict relationships)
proxyan 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
PatternDescription
chain_of_responsibilityapply a chain of successive handlers to try and process the data
cataloggeneral methods will call different specialized methods based on construction parameter
chaining_methodcontinue callback next object method
commandbundle a command and arguments to call later
interpreterdefine a grammar for a language and use it to interpret statements
iteratortraverse a container and access the container's elements
iterator (alt. impl.)traverse a container and access the container's elements
mediatoran object that knows how to connect other objects and act as a proxy
mementogenerate an opaque token that can be used to go back to a previous state
observerprovide a callback for notification of events/changes to data
publish_subscribea source syndicates events/data to 0+ registered listeners
registrykeep track of all subclasses of a given class
servantprovide common functionality to a group of classes without using inheritance
specificationbusiness rules can be recombined by chaining the business rules together using boolean logic
statelogic is organized into a discrete number of potential states and the next state that can be transitioned to
strategyselectable operations over the same data
templatean object imposes a structure but takes pluggable components
visitorinvoke a callback for all items of a collection

Design for Testability Patterns

PatternDescription
dependency_injection3 variants of dependency injection

Fundamental Patterns

PatternDescription
delegation_patternan object handles a request by delegating to a second object (the delegate)

Others

PatternDescription
blackboardarchitectural model, assemble different sub-system knowledge to build a solution, AI approach - non gang of four pattern
graph_searchgraphing algorithms - non gang of four pattern
hsmhierarchical 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:

  • black . This lints your code.
  • Either tox or tox -e ci37 for unit tests.
  • If you have a bash compatible shell, use ./lint.sh.

Contributing via issue triage Open Source Helpers

You can triage issues and pull requests on CodeTriage.