faif / python-patterns Goto Github PK
View Code? Open in Web Editor NEWA collection of design patterns/idioms in Python
A collection of design patterns/idioms in Python
Implementation of the HSM (hierachrical state machine) or
hierachrical --> hierarchical
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.
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:
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.
Understanding how some of the non-obvious patterns work would be aided by simply appending the script output to the bottom for people to read.
They are going to paste this in a shell to see the output anyway.
There is another pattern for the lazy evaluation https://github.com/faif/python-patterns/blob/master/lazy_evaluation.py
called cached_property. It does almost the same as lazy_evaluation.py, but instead of setting a different name on the object dict, it sets the same name, so the actual property will be shadowed (but not lost).
Invalidating the cached value is by simply deleting it.
You can read more about it here: http://www.pydanny.com/cached-property.html
The factory method pattern here is actually simple factory pattern.
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...
python-patterns/structural/flyweight.py
Lines 122 to 123 in 7739094
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
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?
Would you accept PRs about functional programming patterns @faif ? Would probably imply some project restructuring (e.g. putting dirs "behavioral" and "structural" into "oop").
The code from structural/mvc.py can be replaced by a more concise and simpler version:
class Price1(float):
def __str__(self):
return "{:.2f}".format(self)
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.
There is a likely possibility of a missing attribute if a str() is requested. The "state" attribute is defined in the looseleaf code at the bottom of the module, but only read within the actual DP template (https://github.com/faif/python-patterns/blob/master/borg.py#L12). There are no guarantees it'll be set in someone else's implementation. It might be safer to just remove the definition for str.
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
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
A common pattern is page object model and loadable component, I have a source code with them
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:
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
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!
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.
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?
I have just continued as per the other examples, but I don't know why?
Hello there. I noticed that there is no example of the Singleton design pattern. However, I saw an example of Borg https://github.com/faif/python-patterns/blob/master/creational/borg.py I was thinking of adding that. Any thoughts?
The get_registry method defined in RegistryHolder metaclass does not work in BaseRegisteredClass or ClassRegistree.
I tried to define it in class BaseRegisteredClass, and it worked, but I am still confusing about methods defined in metaclass :)<
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...
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:
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
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.
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?
Can you add pattern blackboard? I cannot find this pattern in python on the internet.
Here is description and Java code. It would be very usefull make it easier.
https://en.wikipedia.org/wiki/Blackboard_(design_pattern)
Thank you.
P.S. If I add this request on bad place I am very sorry. I am new here.
The link on the following line is dead. It would be good to get some context for this.
https://github.com/faif/python-patterns/blob/master/behavioral/mediator.py#L3
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?
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?
Creational patterns
Structural patterns
Behavioral patterns
Concurrency patterns
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!
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'
borg singleton method is not really singleton,it is just a shared state to all instances of the class,the better way is processing the new method of the class.
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...
Are the concepts portrayed only from GOF's book on design patterns, or is there any other source also used?
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?
The example does not make use of the method Provider.unsubscribe().
I expected that there would be a "wrapping" method like Subscriber.unsubscribe() for removing itself from the Provider (compare: Subscriber.subscribe() for appending itself to the Provider)?
This commit introduces a SyntaxError on line 27 in publish_subscribe.py
and it renames self.subcribers
to self.subscribe_queue
which causes the other methods not to work anymore: fee0702.
Motivation:
pytest
is stable, extensible, popular etc etcnose
release was on Jun 2, 2015Notes:
pytest
runs unittest.TestCase
wo modificationspytest
is also available in travis env by default@faif (or other maintainers) what do you think?
Could memoization be a pattern fit for this list?
I think we should use Python-3 compatible code for unicode.
from future import unicode_literals
Found here and and all other places wherever required.
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.
This is really not much of an issue. Just that there is supposed to be a new line at the end of every file as per the PEP-8 standards, right?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.