Coder Social home page Coder Social logo

python-patterns's Introduction

python-patterns

A collection of design patterns and idioms in Python.

Current Patterns

Creational Patterns:

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:

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:

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

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 tox or tox -e ci37 before submitting a patch to be sure your changes will pass CI.

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.

python-patterns's People

Contributors

0--key avatar 2ykwang avatar aliciawyy avatar cclauss avatar diopib avatar duboviy avatar duythinht avatar faif avatar fluencydoc avatar gyermolenko avatar hmodaresi avatar ijxsid avatar imankulov avatar jcdenton avatar johntyree avatar lord63 avatar lucasloisp avatar mjanos5 avatar mshcruz avatar osscca avatar rednafi avatar reem avatar spookylukey avatar tamasgal avatar tolstochenkodaniil avatar washwash avatar xingfet avatar xuefeng-zhu avatar yarikoptic avatar yhay81 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

python-patterns's Issues

Is Borg really implemented right ?

I thought that the point of Borg was to allow subclassing. However, the implementation doesn't match expectations in this case:

class Borg:
    __shared_state = {}

    def __init__(self):
        self.__dict__ = self.__shared_state
        self.state = 'Running'

    def __str__(self):
        return self.state

instance0 = Borg()
instance1 = Borg()

instance0.state = 'Idle'

print instance1  # prints 'Idle', instead of 'Running', as expected

borg = Borg()
borg.state = 'Idle'


class YourBorg(Borg):
    pass

borg = YourBorg()
print borg  # prints 'Running' instead of 'Idle', **not** as expected

Are you sure that Borg supports setting attributes in the constructor ?

It looks like it defeats the purpose of Borg...

Aren't some of these a bit silly?

I struggle to see the point of some of these patterns. They strike me as overly verbose implementations of things that are practically free in a dynamic language with first-class functions. I'm looking at YOU strategy pattern...

The file labled as 'abstract_factory.py' isn't really an abstract factory.

python-patterns / abstract_factory.py

The idea of an abstract factory is you tell it a super class or interface, and it returns you the best matching subclass. What the file has in there is a simple manager with a hard coded switch.

Here's an example of an abstract factory pattern, https://github.com/wiredrive/wtframework/blob/master/wtframework/wtf/web/page.py#L151
Notice that it queries python for subclasses of a given super class or interface, via '__itersubclasses'. This gets a list of all subclasses that implements the super class, then constructs and returns the best matching subclass to the given conditions.

Project folder structure

Can I suggest to change project structure to this?

patterns/
  behavioral
     ...
  creational
     ...
  structural
     ...
  ...
tests/
  behavioral
     ...
  creational
     ...
  structural
     ...
setup.cfg
.travis.yml
...

It is more common among python packages.
It would be possible to run commands like pytest patterns or flake8 patterns

Enhance documentation with brief, high-level descriptions/usage of patterns

I'd hate to think that I'm the only one of the thousands of people who have starred this project, but I would greatly benefit from a list of the purposes of each pattern in the README document. It would keep me/us/others from having to peruse each individual module to determine their use when there are so many other interesting things that that equally demand attention.

Thoughts?

[question] strategy pattern class methods

hi, thank you for this amazing repository. I don't understand why the strategy pattern is not an abstract class, i.e., using @abc.abstractmethod. Was it done this way to provide a default strategy?

Calling business logic on different physical machine

In 3-tier.py the UI class makes a normal call to the business logic class as if they both run on the same machine, rather it must cater for calling business logic that resides on a centralized separate machine. I hope I'm not missing the point.

Chain pattern is overcomplicated

Hi.
Chain pattern seems overcomplicated (imho).

The file has more or less standard implementation with classes with handlers (client1 = Client()) but also adds comparison with implementation with coroutines (client2 = ClientCoroutine()).
At http://www.dabeaz.com/coroutines/ (docstring description link) I couldn't find this implementation to read more on "why" or what David was trying to illustrate. My assumption is that he concentrated here on generator/coroutine part, not chain pattern itself.

I like simplicity, especially in example code. Therefore I find coroutine implementation unnecessary here. What do you think?

Hyperlink is broken in facade.py

This link is in a comment at the top of the page for facade.py

http://dpip.testingperspective.com/?p=26

And it doesn't seem to go to a blog post. Should it be updated or removed?

Python Patterns Organization

Hi @faif, what do you think about to creating a GitHub organization for a central place of python pattern related stuff? I have a lot of python pattern example references to books here (paste "python" in the search field) which make more sense in a more "python oriented" context. But I think these book references would "waste" your repository. But they would be quite suitable in an organization beside your repository...

Generate patterns automatically

Can we generate patterns automatically? Take strategy pattern as an example, we can generate codes of the pattern with the names of strategies and class employing them

repository structure

Hello,
I found this repository very useful.
For improve readability it would be nice to structure this repository in modules/ folder (creational, structural).

What do you think about it?

Updating the source to Python 3?

Just a quick comment--looking over the source, do you think it'd be a good idea to update to Python 3, e.g. using type annotations and Python 3 syntax?

typo in hsm.py

Implementation of the HSM (hierachrical state machine) or

hierachrical --> hierarchical

Needs a COPYRIGHT/LICENSE file

I haven't checked if any of the examples is simply completely copied from the web, when it would need to retain original copyright/license notice, or all of them could be claimed to be owned by contributors to this repository, but the point is that there should some clear statement on copyright/licenses for the files and possibly for the collection as a whole as well.

Short descriptions

It would be useful to have some more detailed descriptions for each pattern. I would put them in the comments above the code. The main questions would be:

  • What the pattern is?
  • What the current example does?
  • Where can the pattern be used practically (or is used in known open-source projects)?

Some of the patterns have comments or are obvious, but not all of them. Also, I think, that people with different computer science knowledge will check them, so it would be valuable to describe the patterns to them.

Singleton Pattern

I want to create a simple singleton pattern.

Whose code looks something like this.

class Singleton(object):
  _instance = None
  def __new__(self):
    if not self._instance:
      self._instance = super(Singleton, self).__new__(self)
      self.num = 10
    return self._instance

x = Singleton()
print x.num #10
x.num = 20
z = MyClass()
print z.num #20 

I understand that Borg has a singleton class too. But this I felt is a much simpler example.
If you guys give 👍 I will go ahead and send a PR

cc @faif

Source of these patterns

Are the concepts portrayed only from GOF's book on design patterns, or is there any other source also used?

Wrong example for decorator pattern

Hello,

Based on my materials decorator pattern should be implemented differently. Decorator pattern is not about python decorator or how to change implementation by using python decorator syntax but how to change object's behavior by wrapping it by another.
I found one example for python: https://wiki.python.org/moin/DecoratorPattern
I don't know if you have access but this is second material (not for python): https://app.pluralsight.com/player?course=patterns-library&author=brian-lagunas&name=decorator&clip=0&mode=live

Template pattern functional implementation looks weird

I find current implementation a bit strange.
Usually template has obligatory and customizable steps, structured in some kind of base algorithm.

I think it would be better (instead of def make_template factory) to show just two concrete algorithms based on same base template. One will overwrite some customizable step, another will just skip it.

I also tried to write it using functions and it gets weird pretty quick. Here is an example of what I wrote:

def template_method_alike(get_raw_data=None, validate=None, close_session=default_session_closer):
    if not get_raw_data:
        print('please provide necessary methods')
        return

    data = get_raw_data()
    if not data:
        print('no data')
        return

    if validate:
        validate(data)  # optional
    else:
        print('no validation')

    close_session()

I don't like how we need to check if some steps are defined and others can be skipped.

I think that class based implementation would look better.
Implementation like this

class AlgorithmA(BaseAlgorithm):

    def do_step_1(self):
        print('do step 1 for Algorithm A')

    def do_step_2(self):
        print('do step 2 for Algorithm A')

tells me "I, AlgorithmA, follow template of BaseAlgorithm.

Make use of informal string representation for abstract_factory

Hey, thanks for putting this together. I noticed that in the abstract_factory.py script, the show_pet function does not format the strings together:

    def show_pet(self):
        """Creates and shows a pet using the
        abstract factory"""

        pet = self.pet_factory.get_pet()
        print("This is a lovely", pet)
        # Prints ('This is a lovely', <__main__.Cat instance at...>)
        print("It says", pet.speak())
        # Prints ('It says', 'meow')
        print("It eats", self.pet_factory.get_food())
        # Prints ('It eats', 'cat food')

This leads to two things: Odd formatting, and printing the memory address of pet, instead of the class name. I suggest we change it to:

    def show_pet(self):
        """Creates and shows a pet using the
        abstract factory"""

        pet = self.pet_factory.get_pet()
        print "This is a lovely {}".format(pet)
        # Prints This is a lovely Cat
        print "It says {}".format(pet.speak())
        # Prints It says meow
        print "It eats {}".format(self.pet_factory.get_food())
        # Prints It eats cat food

That way, we can make the print functions more pythonic (dropping the unnecessary parentheses), and make use of the __str__() functions defined within the Pet class.

Thanks!

Design for Testability Patterns

I would like to port the "Design for Testability" pattern examples from xUnit Test Patterns: Refactoring Test Code (the patterns of this category are actually no test code but production code patterns) which are in Java and VB to Python. Anyone interested in joining...

Short and eventually outdated descriptions of the patterns can be found here:

  • Dependency Injection
    • Parameter Injection (implementation variant) ✔️
    • Constructor Injection (implementation variant) ✔️
    • Setter Injection (implementation variant) ✔️
  • Dependency Lookup
  • Humble Object
    • Poor Man's Humble Object (implementation variant)
    • True Humble Object (implementation variant)
    • Subclassed Humble Object (implementation variant)
    • Humble Dialog (context variant)
    • Humble Executable (context variant)
    • Humble Transaction Controller (context variant)
    • Humble Container Adapter (context variant)
  • Test Hook
    • System Under Test Hook (implementation variant)
    • Depended-on Component Hook (implementation variant)

[Infrastructure] Testing outputs

update on idea of testing outputs as docstrings (e.g. with python -m doctest):
I couldn't find easy way to generate docstrings for def main()

By "testing outputs" I mean to compare script output with ### OUTPUT ### section at the bottom of the file.
Structuring scripts like that:

def main():
    ...

if __name__ == "__main__":
   main()

allows imports of main in tests to evaluate and compare outputs.

It would also be more convenient to have ### OUTPUT ### section as variable or docstring, so we do not need to parse file for such comparisons

3-tier.py and mvc.py are almost identical

3-tier.py and mvc.py are almost identical from a high level point of view. The only difference is that in 3-tier.py the logic instance and the ui instance may be assigned to the data instance explicitly. In mvc.py the model instance and the view instance is assiged to the controller instance statically during its creation.

Error in the iterator.py

Hello,

There is an error in the iterator.py.

count_to_two and count_to_five returned the same. The count param of the count_to function is not used.

In this changeset is the problem:

1ccc5ed#iterator.py

__getattr__ usage in some Classes

Not so much an issue or a bug, but I noticed that under some getattr usages for eg: https://github.com/faif/python-patterns/blob/master/structural/composite.py#L46

if name in self

But I think it is not necessary. Accessing self.name or getattr(self, 'name') first checks in self.__dict__ by default and only then goes into __getattr__() for an item that was not in self dict.
Unless I am missing something. Just wanted to drop a note. Great set of examples, btw. Thanks!

Move from nose to pytest for testing

Motivation:

  • pytest is stable, extensible, popular etc etc
  • last nose release was on Jun 2, 2015

Notes:

  • pytest runs unittest.TestCase wo modifications
  • pytest is also available in travis env by default

@faif (or other maintainers) what do you think?

When flyweight.py is run as skript it raises an error

When flyweight.py is run as skript the following output is generated:

<Card: 9h> <Card: 9h>
True True
50022776 50022776
True
False
Traceback (most recent call last):
  File "D:\Users\Florian\Documents\GitHub\python-patterns\flyweight.py", line 92, in <module>
    instances_pool = getattr(Card2, 'pool')
AttributeError: type object 'Card2' has no attribute 'pool'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.