Mostly, it's Java written with Python syntax, specially the gang-of-four patterns. I recall it being even more java-like, so, progress?<p>The stuff that is actually idiomatic python is either too convoluted or rather obvious.<p>I know this comes across rather mean, but this is just not a good resource, for either beginners (not very idiomatic) or experienced developers (trivial patterns with trivial examples). There's maybe 2 or 3 good ideas in there, but even those I might be hard pressed to find a real usecase for.
For an alternative perspective, allow me to present some classic talks from Raymond Hettinger.<p>First, some generic tips on how to write Python code that's pleasant to work with: <a href="https://youtu.be/OSGv2VnC0go" rel="nofollow">https://youtu.be/OSGv2VnC0go</a><p>And then this one digs more specifically into how not to write Python like it's Java, starting at 12:40 (with talking about why leading up to that): <a href="https://youtu.be/wf-BqAjZb8M" rel="nofollow">https://youtu.be/wf-BqAjZb8M</a>
I'm confused by the Borg pattern. It seems like a singleton that tricks the user into believing there are multiple instances (very bad imo). Is there any advantage over singleton? Maybe some kind of `__dict__` behavior I'm not aware of?
I've had Python code reviewed in the past by senior devs from more of a Java/C# background, who encouraged me to read the GoF and rewrite classes using the abc (abstract base class) library, staticmethod/classmethod decorators, etc. I never quite understood the value of it in Python. But the fact that those are included in the stdlib makes me think that they must have some clear use cases.
Picking very specifically on the builder pattern: the whole point is to solve one or more of the following problems:<p>1. creating complex objects and having them valid at creation<p>2. many optional arguments for an object's construction<p>3. similar types for object construction<p>For e.g. in Java you might see something like:<p><pre><code> Point p = new Point(10, 0, 5); // (x=10, z=5)
Point q = new Point(10, 2); // (x=10, y=2)
</code></pre>
which may be problematic because<p>1. y needs to be specified explicitly to 0, because you can't expose an overloaded constructor that takes x and z (that would clash with the constructor that takes x and y<p>2. It _may_ not be evident that new Point(10, 0, 5); passes x, y and z in that order<p>3. It ties the constructor to the implementation. You can never expose a Point(double radius, double theta) constructor because that would clash with the Point(double x, double y) constructor.<p>The builder would solve all of these problems:<p><pre><code> Point p = Point.newBuilder()
.setX(10)
.setZ(5)
.build();
</code></pre>
Python however doesn't necessarily need this pattern because idiomatically solves all three of these problems by providing<p>1. named arguments, and<p>2. default arguments<p>so you could have:<p><pre><code> p = Point(x=10, z=5)
q = Point(10, 2)
t = Point(radius=5, theta=45)
</code></pre>
I feel the post completely glosses over this by providing a single super-class with the appropriate constructor, and overriding the methods in the sub-classes. What if I just have a single class that I want a builder for? I don't think it showcases the builder pattern at all, just method overloading in classes.
I recently began reading GOF (a bit into the behavioral patterns at the moment). A lot of those patterns were ideas I had been familiar with, but not through a formal specification, likely due to seeing so much code inspired by the book. I just find it so fascinating that these patterns were written about in 1994 (?) and they were pretty well designed.<p>I will say, the book is heavily focused on OOP, which has fallen out of favor a bit with newer languages (but obviously very alive), and it's almost like a time piece. Feels like OOP was seen as this answer to so many business problems and organization of code.<p>Just interesting to imagine OOP at a time when it was new and exciting, since I grew up at a time when Java was ubiquitous and everyone was at least a little OO.
I wish there was a pattern to encapsulate data and functions from a module.<p>So you could do:<p><pre><code> import greeter
greet1 = encapsulate(greeter)
greet2 = encapsulate(greeter)
greet1.name = 'Joe'
greet2.name = 'Sue'
greet1.greet()
greet2.greet()
</code></pre>
And greeter.py would look like this:<p><pre><code> name = 'nobody'
def greet():
print ('Hello '+name)
</code></pre>
Output:<p><pre><code> Hello Joe
Hello Sue
</code></pre>
This would be so much nicer and leaner than classes.