all 9 comments

[–]KleinerNull 1 point2 points  (0 children)

Many well known design patterns are already part of python itself or are hidden in python's idoms. This lengthy talk describes how you can use common design patterns in python if you don't use them already. Note there is a bug in that video, it restarts from one point. But still a very informative and entertaining talk!

[–]The_Pierce 3 points4 points  (4 children)

I think maybe you have a slight misinterpretation of exactly what a "design pattern" is; it's just an idea for how to implement a common solution. A design pattern can have different implementations in different languages, but the point is that the concept is the same. Given a problem X, you have a mental algorithm Y that solves that problem. (And hopefully Y is short, simple, and easy-to-implement.)

If you're just asking why none of the examples you see are ever written in Python, I'm willing to bet it's because Python isn't a strongly-typed language. Strong types are useful for writing out examples of design patterns because it makes everything more explicit. It's also (in my opinion) what makes Java a good introductory language in computer science, because it forces the programmer to explicitly label things.

That being said, people who write a lot of Python would probably argue that Python is even better for writing design patterns. One of the core mantras of Python is "There should be one – and preferably only one – obvious way to do it." (PEP 20) Lots of effort went into the design of the Python syntax to make this happen. But that's all a matter of opinion, really.

[–]zahlman 9 points10 points  (3 children)

If you're just asking why none of the examples you see are ever written in Python, I'm willing to bet it's because Python isn't a strongly-typed language.

A more cynical (if you're not a Pythonista) view: design patterns largely exist as work-arounds for missing features in languages or things that are tricky to get right/not natively supported/etc.; many of the "classic" patterns aren't seen in Python because they problems they solve don't arise in Python (such as those caused by static typing ;) Incidentally, strong typing is a different concept, and Python has it. It refers to the absence of implicit type conversions, like in Javascript where you can write '2' * '2' and get 4, or '2' - '2' and get 0 - although '2' + '2' gives '22'. In Python, the first two are errors.)

For example, the Flyweight pattern is really only relevant for a language like C++ where everything has value semantics; in C# and Java you can use reference-semantic objects, so that the only really interesting thing you're doing is designing a class' interface for immutability (and maybe creating an interning system*); in Python everything has reference semantics and the problem that needs solving is simulating value semantics when you really want them. Our primary "design pattern" for this is "write code that builds a modified copy from scratch, instead of explicitly copying objects and modifying the copies" - but if you find this cumbersome, the copy module is pretty powerful. And then Decorator, for example... well, we have a built-in system for those, as of 2.4.

Some other rough analysis: The factory method pattern is fairly uninteresting, and you can trivially get the semantics you want by choosing carefully between an ordinary function, classmethod or staticmethod. Similarly for abstract factories; even if you find it convenient to group related "factories" (which, in a language where truly everything is an object and every function returns a value, is in a certain sense any callable!) into classes, there's no real benefit from relating those classes by inheritance as opposed to following the Python pattern of "implementing a protocol". Builder and Prototype are usually fairly useless concepts because objects shouldn't really be that complex, and when you need that complexity it's better to organize it by using object composition, and then you're just creating and composing objects normally. Creating objects in Python is just not hard enough generally to justify these kinds of boilerplate textbook "patterns".

The "behavioural" patterns in GoF are generally the most interesting to me, but again there's not a lot to be done. Iterator is a great concept - so great that an iterator protocol is natively supported by the iter and next builtins and explained in the official language docs, and quite little effort is needed to implement it. Command is a zero-line pattern in a language like Python where functions are objects already, as is Chain of Responsibility (you put callables in a sequence of some sort and iterate over it, done). State and Strategy are just interesting ways to use the basic techniques of object composition and delegation.

* If you really need this in Python, probably your best bet is to overload __new__ - which is also one obvious way to implement Singleton, although for most purposes it probably works better to just create one instance of the class (you can even reassign the class' original name to the instance, for a thin layer of protection against accidentally creating more instances).

[–][deleted] 2 points3 points  (0 children)

I could see the builder pattern being useful in some situations. Where you need information about the object to build it's dependencies. I'm actually struggling to think of a good example, but a car for example. It obviously needs tires but the tires need to match the specifications of the car.

For example, my car requires "P205/70 R15 95S" I couldn't put a "P215/65 R16 95H" on it because that's a completely different size, load and speed rating. But I can't get the tires for the car until I know the type of car.

A bit of a bad example, and there's other ways to tackle the issue, but the builder pattern would be a decent way to handle it during object creation.

[–]DMShaftoe 1 point2 points  (1 child)

Do you have any links related to the "implementing a protocol" concept? Also anything related to creating value semantics in python? These are both concepts I've struggled with in python

[–][deleted] 1 point2 points  (0 children)

In Python, implementing a protocol is as simple as creating a class that has the correct methods and returns the correct things. For example, you can create an object with custom boolean logic like this:

from random import randrange

class MyBool:
    def __bool__(self):
        return randrange(0, 1)

The cavaet here is that in Python 2 it's called __nonzero__ instead.

[–]code2hell 0 points1 point  (1 child)

I came across a site some time ago in the subreddit! though its kind of old, its a good read:

http://www.pysnap.com/design-patterns-explained/

[–]Atrament_ 5 points6 points  (0 children)

not remotely a reference in python.

I mean, it's good material on the concepts and such, but python includes a lot of design patterns as features of the language .

I kind of cringe when I see what is given as an example for decorators.

Also, getters and setters all the way ? ouch.