Created by: spookylukey
Replace with link to video showing why many patterns are unnecessary.
In my opinion, the linked repos (python-patterns and PyPatterns) are really unhelpful ways of thinking about patterns in Python - they are anti-patterns in Python, and not something that should be promoted.
Basically, most of the patterns popular in Java world are "invisible or simpler" in dynamic languages like Python (according to Peter Norvig - http://www.norvig.com/design-patterns/ ). This is due to:
- the pattern being built in (e.g. iterator)
- various language features, especially:
- first class functions (command, strategy, template-method, visitor)
- first class types (factory, abstract factory, flyweight, factory method, state, proxy, chain-of-responsibility)
Of the two links, PyPatterns is the worst, and actually encourages importing a library to get functionality that only increases the amount of code you have to write. I see that it was added because someone wanted something they could actually import
. However, this comes from people thinking in Java - but Python is not Java without the compile. There is negative value in using this kind of repo - Python makes the pattern invisible or simpler, by adding an import and base classes you have only made life hard for yourself.
For example, Factory and Abstract Factory pattern:
https://github.com/tylerlaberge/PyPattyrn#factory-pattern https://github.com/faif/python-patterns/blob/master/creational/abstract_factory.py
Once you understand that Python has first class types, these become totally pointless.
Here is a class in Python:
class A:
pass
And here is a factory for it:
A
(A
is it's own factory - when you call it, it produces an object of type A. There is no new
keyword in Python.)
And here is a factory that you can assign to a variable, or pass as an argument to a function/method:
A
(First class types.)
And here is a factory if you wanted to create A
in a non-default way:
lambda: A(some_parameter=123)
Or, in a builtin-standard-but-non-default way
class A:
def __init__(self, enabled=True)
self.enabled = enabled
@classmethod
def create_disabled(cls):
return cls(enabled=False)
# Factory callable you can pass around:
A.create_disabled
These are the idiomatic ways to do these things. If you are writing anything more than that, you are doing it wrong.
Even when the pattern is bigger than invisible, its implementation is often massively simpler in Python. The linked repositories often use classes with no state and a single method. This is pointless - we should be deleting such classes and replacing them a single callable - see Stop Writing Classes
PyPatterns even includes an implementation of iterator and iterable - when these are built in to Python!
I was going to submit PRs to the linked repositories, but most of the PRs would involve deleting 90% of the code, which is unlikely to be accepted, I thought it better to submit this PR first.