Convert Figma logo to code with AI

faif logopython-patterns

A collection of design patterns/idioms in Python

40,339
6,932
40,339
14

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

Pros of design-patterns-for-humans

  • Written in plain English, making it more accessible to beginners
  • Covers a wide range of design patterns with real-world examples
  • Includes visual diagrams to illustrate pattern structures

Cons of design-patterns-for-humans

  • Examples are in PHP, which may not be ideal for Python developers
  • Less comprehensive coverage of patterns compared to python-patterns
  • Lacks detailed implementation code for some patterns

Code Comparison

python-patterns (Strategy Pattern):

class QuackStrategy(object):
    def quack(self):
        pass

class LoudQuackStrategy(QuackStrategy):
    def quack(self):
        return "QUACK!"

design-patterns-for-humans (Strategy Pattern):

interface SortStrategy {
    public function sort(array $dataset): array;
}

class BubbleSortStrategy implements SortStrategy {
    public function sort(array $dataset): array {
        // Sorting logic here
    }
}

Both repositories aim to explain design patterns, but python-patterns focuses on Python implementations, while design-patterns-for-humans provides a more general overview with PHP examples. python-patterns offers more extensive code samples, whereas design-patterns-for-humans emphasizes simplicity and accessibility for beginners.

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.

Current Patterns

Creational Patterns:

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:

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:

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

Videos

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

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.

Then either:

  • tox or tox -e ci37 This runs unit tests. see tox.ini for further details.
  • If you have a bash compatible shell use ./lint.sh This script will lint and test your code. This script mirrors the CI pipeline actions.

You can also run flake8 or pytest commands manually. Examples can be found in tox.ini.

Contributing via issue triage Open Source Helpers

You can triage issues and pull requests which may include reproducing bug reports or asking for vital information, such as version numbers or reproduction instructions. If you would like to start triaging issues, one easy way to get started is to subscribe to python-patterns on CodeTriage.

AI codebase assistance

The folks at Mutable.ai have built an AI assistant that is codebase-aware. Give it a try Mutable.ai Auto Wiki