Python Design Patterns: For Sleek And Fashionable Code

Let’s say it again: Python is a high-level programming language with dynamic typing and dynamic binding. I would describe it as a powerful, high-level dynamic language. Many developers are in love with Python because of its clear syntax, well structured modules and packages, and for its enormous flexibility and range of modern features.

In Python, nothing obliges you to write classes and instantiate objects from them. If you don’t need complex structures in your project, you can just write functions. Even better, you can write a flat script for executing some simple and quick task without structuring the code at all.

At the same time Python is a 100 percent object-oriented language. How’s that? Well, simply put, everything in Python is an object. Functions are objects, first class objects (whatever that means). This fact about functions being objects is important, so please remember it.

So, you can write simple scripts in Python, or just open the Python terminal and execute statements right there (that’s so useful!). But at the same time, you can create complex frameworks, applications, libraries and so on. You can do so much in Python. There are of course a number of limitations, but that’s not the topic of this article.

However, because Python is so powerful and flexible, we need some rules (or patterns) when programming in it. So, let see what patterns are, and how they relate to Python. We will also proceed to implement a few essential Python design patterns.

Why Is Python Good For Patterns?

Any programming language is good for patterns. In fact, patterns should be considered in the context of any given programming language. Both the patterns, language syntax and nature impose limitations on our programming. The limitations that come from the language syntax and language nature (dynamic, functional, object oriented, and the like) can differ, as can the reasons behind their existence. The limitations coming from patterns are there for a reason, they are purposeful. That’s the basic goal of patterns; to tell us how to do something and how not to do it. We’ll speak about patterns, and especially Python design patterns, later.

Python is a dynamic and flexible language. Python design patterns are a great way of harnessing its vast potential.

Python’s philosophy is built on top of the idea of well thought out best practices. Python is a dynamic language (did I already said that?) and as such, already implements, or makes it easy to implement, a number of popular design patterns with a few lines of code. Some design patterns are built into Python, so we use them even without knowing. Other patterns are not needed due of the nature of the language.

For example, Factory is a structural Python design pattern aimed at creating new objects, hiding the instantiation logic from the user. But creation of objects in Python is dynamic by design, so additions like Factory are not necessary. Of course, you are free to implement it if you want to. There might be cases where it would be really useful, but they’re an exception, not the norm.

What is so good about Python’s philosophy? Let’s start with this (explore it in the Python terminal):

>>> import this
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

These might not be patterns in the traditional sense, but these are rules that define the “Pythonic” approach to programming in the most elegant and useful fashion.

We have also PEP-8 code guidelines that help structure our code. It’s a must for me, with some appropriate exceptions, of course. By the way, these exceptions are encouraged by PEP-8 itself:

“But most importantly: know when to be inconsistent – sometimes the style guide just doesn’t apply. When in doubt, use your best judgment. Look at other examples and decide what looks best. And don’t hesitate to ask!”

Combine PEP-8 with The Zen of Python (also a PEP - PEP-20), and you’ll have a perfect foundation to create readable and maintainable code. Add Design Patterns and you are ready to create every kind of software system with consistency and evolvability.

Python Design Patterns

What Is A Design Pattern?

Everything starts with the Gang of Four (GOF). Do a quick online search if you are not familiar with the GOF.

Design patterns are a common way of solving well known problems. Two main principles are in the bases of the design patterns defined by the GOF:

Program to an interface not an implementation.

Favor object composition over inheritance.

Let’s take a closer look at these two principles from the perspective of Python programmers.

Program to an interface not an implementation

Think about Duck Typing. In Python we don’t like to define interfaces and program classes according these interfaces, do we? But, listen to me! This doesn’t mean we don’t think about interfaces, in fact with Duck Typing we do that all the time.

Let’s say some words about the infamous Duck Typing approach to see how it fits in this paradigm: program to an interface.

The advantages are obvious. We can restrict what methods of the wrapped class to expose. We can inject the persister instance in runtime! For example, today it’s a relational database, but tomorrow it could be whatever, with the interface we need (again those pesky ducks).

Composition is elegant and natural to Python.

Behavioral Patterns

Behavioural Patterns involve communication between objects, how objects interact and fulfil a given task. According to GOF principles, there are a total of 11 behavioral patterns in Python: Chain of responsibility, Command, Interpreter, Iterator, Mediator, Memento, Observer, State, Strategy, Template, Visitor.

Behavioural patterns deal with inter-object communication, controlling how various objects interact and perform different tasks.

I find these patterns very useful, but this does not mean the other pattern groups are not.

Iterator

Iterators are built into Python. This is one of the most powerful characteristics of the language. Years ago, I read somewhere that iterators make Python awesome, and I think this is still the case. Learn enough about Python iterators and generators and you’ll know everything you need about this particular Python pattern.

Chain of responsibility

This pattern gives us a way to treat a request using different methods, each one addressing a specific part of the request. You know, one of the best principles for good code is the Single Responsibility principle.

Every piece of code must do one, and only one, thing.

This principle is deeply integrated in this design pattern.

For example, if we want to filter some content we can implement different filters, each one doing one precise and clearly defined type of filtering. These filters could be used to filter offensive words, ads, unsuitable video content, and so on.

Command

This is one of the first Python design patterns I implemented as a programmer. That reminds me: Patterns are not invented, they are discovered. They exist, we just need to find and put them to use. I discovered this one for an amazing project we implemented many years ago: a special purpose WYSIWYM XML editor. After using this pattern intensively in the code, I read more about it on some sites.

The command pattern is handy in situations when, for some reason, we need to start by preparing what will be executed and then to execute it when needed. The advantage is that encapsulating actions in such a way enables Python developers to add additional functionalities related to the executed actions, such as undo/redo, or keeping a history of actions and the like.

Creational Patterns

Let’s start by pointing out that creational patterns are not commonly used in Python. Why? Because of the dynamic nature of the language.

Someone wiser than I once said that Factory is built into Python. It means that the language itself provides us with all the flexibility we need to create objects in a sufficiently elegant fashion; we rarely need to implement anything on top, like Singleton or Factory.

In one Python Design Patterns tutorial, I found a description of the creational design patterns that stated these design “patterns provide a way to create objects while hiding the creation logic, rather than instantiating objects directly using a new operator.”

That pretty much sums up the problem: We don’t have a new operator in Python!

Nevertheless, let’s see how we can implement a few, should we feel we might gain an advantage by using such patterns.

Singleton

The Singleton pattern is used when we want to guarantee that only one instance of a given class exists during runtime. Do we really need this pattern in Python? Based on my experience, it’s easier to simply create one instance intentionally and then use it instead of implementing the Singleton pattern.

But should you want to implement it, here is some good news: In Python, we can alter the instantiation process (along with virtually anything else). Remember the __new__() method I mentioned earlier? Here we go:

Create one instance somewhere at the top-level of your application, perhaps in the config file.

Pass the instance to every object that needs it. That’s a dependency injection and it’s a powerful and easily mastered mechanism.

Dependency Injection

I don’t intend to get into a discussion on whether dependency injection is a design pattern, but I will say that it’s a very good mechanism of implementing loose couplings, and it helps make our application maintainable and extendable. Combine it with Duck Typing and the Force will be with you. Always.

I listed it in the creational pattern section of this post because it deals with the question of when (or even better: where) the object is created. It’s created outside. Better to say that the objects are not created at all where we use them, so the dependency is not created where it is consumed. The consumer code receives the externally created object and uses it. For further reference, please read the most upvoted answer to this Stackoverflow question.

It’s a nice explanation of dependency injection and gives us a good idea of the potential of this particular technique. Basically the answer explains the problem with the following example: Don’t get things to drink from the fridge yourself, state a need instead. Tell your parents that you need something to drink with lunch.

Python offers us all we need to implement that easily. Think about its possible implementation in other languages such as Java and C#, and you’ll quickly realize the beauty of Python.

We inject the authenticator and authorizer methods in the Command class. All the Command class needs is to execute them successfully without bothering with the implementation details. This way, we may use the Command class with whatever authentication and authorization mechanisms we decide to use in runtime.

We have shown how to inject dependencies through the constructor, but we can easily inject them by setting directly the object properties, unlocking even more potential:

Again, we just demonstrated how implementing this wonderful design pattern in Python is just a matter of using the built-in functionalities of the language.

Let’s not forget what all this means: The dependency injection technique allows for very flexible and easy unit-testing. Imagine an architecture where you can change data storing on-the-fly. Mocking a database becomes a trivial task, doesn’t it? For further information, you can check out Toptal’s Introduction to Mocking in Python.

You may also want to research Prototype, Builder and Factory design patterns.

Structural Patterns

Facade

This may very well be the most famous Python design pattern.

Imagine you have a system with a considerable number of objects. Every object is offering a rich set of API methods. You can do a lot of things with this system, but how about simplifying the interface? Why not add an interface object exposing a well thought-out subset of all API methods? A Facade!

Facade is an elegant Python design pattern. It's a perfect way of streamlining the interface.

I would say it is a well written method with dependency injection, which allows for great extensibility. Say you want to log to some UDP socket instead to a file,you know how to open this UDP socket but the only problem is that the socket object has no write() method. You need an Adapter!

But why do I find adapter so important? Well, when it’s effectively combined with dependency injection, it gives us huge flexibility. Why alter our well-tested code to support new interfaces when we can just implement an adapter that will translate the new interface to the well known one?

You should also check out and master bridge and proxy design patterns, due to their similarity to adapter. Think how easy they are to implement in Python, and think about different ways you could use them in your project.

Decorator

Oh how lucky we are! Decorators are really nice, and we already have them integrated into the language. What I like the most in Python is that using it teaches us to use best practices. It’s not that we don’t have to be conscious about best practices (and design patterns, in particular), but with Python I feel like I’m following best practices, regardless. Personally, I find Python best practices are intuitive and second nature, and this is something appreciated by novice and elite developers alike.

The decorator pattern is about introducing additional functionality and in particular, doing it without using inheritance.

So, let’s check out how we decorate a method without using built-in Python functionality. Here is a straightforward example.

It is important to note that you are not limited to functions as decorators. A decorator may involve entire classes. The only requirement is that they must be callables. But we have no problem with that; we just need to define the __call__(self) method.

You may also want to take a closer look at Python’s functools module. There is much to discover there!

Conclusion

I have shown how natural and easy is to use Python’s design patterns, but I have also shown how programming in Python should be easy going, too.

“Simple is better than complex,” remember that? Maybe you have noticed that none of the design patterns is fully and formally described. No complex full-scale implementations were shown. You need to “feel” and implement them in the way that best fits your style and needs. Python is a great language and it gives you all the power you need to produce flexible and reusable code.

However, it gives you more than that. It gives you the “freedom” to write really bad code. Don’t do it! Don’t Repeat Yourself (DRY) and never write code lines longer than 80 characters. And don’t forget to use design patterns where applicable; it’s one of the best ways to learn from others and gain from their wealth of experience free of charge.

About the author

Andrei is a seasoned IT professional with much experience in a number of software technologies from low level programming to complex systems design and implementation. He has an extensive knowledge (Prince 2 and Agile) and experience in project management. He also has done software design, modeling, development, debugging, and optimization; worked in C#.NET, C, Python, PHP, UML, and UP. [click to continue...]

Comments

Awesome. You have to break your back twice in C#/Java to do awesomeness like this.
Especially the functional decorator and DI. I prefer to decide the decorators at runtime in C# like this:
static Action<T> Y(Action<T> x, IEnumerable<Action<Action<T>, T>> y)
{
if (y.Count() == 0)
return x;
return
Y(a => y.First()(x, a), y.Skip(1).Take(y.Count() - 1));
}
Thin function Y depending on list of y decorators will decorate recursuvely:
f = f1 ( f2 ( f3 ( .... fn (x) ) ) )
But it's limited to 1 argument only for type safety and speed.
Don't know yet how to do it in Python but your article will help a lot.
I LIKE THIS.

Bernardo Leon

If I understood well there is a typo here:
upd_logger = SocketWriter('1.2.3.4', '9999')
log('Something happened', udp_destination)
what you are passing to log is upd_logger right? because udp_destination doesn't even exist.
If python could handle threads as nicely as Java it would be so great! Nevertheless thank you for this great post!

Vladimir Voznesensky

Python gives a lot of freedom, it allows programmers to shoot each over and their own feet by 100500 ways.
Erlang does not give you much freedom, but you do not need design patterns to prevent your programmers to shoot each other's feet.
So, use Erlang for industrial coding.

Thomas Maurin

Great post, great examples. Thanks!
Maybe you could expand on your statement concerning Factories? (That they are built into Python.) I'm not sure to grasp what you have in mind about that.

Ivan Velichko

I can't say something about Erlang, however there is almost always only the one right way to do something in Python. Furthermore, it's one of the main features of this language. While you are looking for a suitable way to make a loop (establish an inheritance property, parse ULRs, etc.) in many other langs like JS, Ruby, C++ and so on, in Python you can concentrate all your attention directly on business tasks.

Miguel

blagodarya Andrei
really nice article, really nice writing and really nice topic. You made me want to reopen my GoF book and remind me also how much I am missing python even if my experience with the language was just some 6 months as much.

Miguel

I had the same concern :)

Ivan Velichko

Let's skip recursion because it doesn't relate to the language syntax and consider the reminder. Each of this ways has one preferable scenario to be used in. Use `for` to iterate over collections (yeah, I know about range/xrange), use `while` to iterate while some expression holds (including making loops for N iterations, because `for _ in range(42)` is ugly in my opinion) and use map/reduce/itertools if you would like to follow functional style. And now let's take a look, for example, at Ruby. I like Ruby, it's kinda shiny diamond. However, here are the ways you can make loops for N iterations:
`for i in 1..1000 do ... end`
`(1..100).each do |i| ... end`
`10.times do |i| ... end`
`10.times{ |i| ... }`
`1.upto(10) ...`
`10.downto(1) ...`
`while`
and maybe something else.
I use a word `loop` in my original comment as a hyperbole. However, one can see that it really works even with loops. In my opinion the main reason for "having the one right way" vs "lang doesn't restrict you how to do it" is in the language philosophy. And I like Python's approach.

Vladimir Voznesensky

You like Python's design patterns, PEP8, etc. hell because it gives you a lot of freedom and it takes you into a central position of development process as a indispensable guru.
Well, everybody loves to be indispensable employee, but every employer's nightmare is to deal with indispensable employees.
Anyway, employer pays money and orders the music. So, I warn employers: Do not trust Python gurus, consider self-restrictive enterprise-hardened functional Erlang.

Vladimir Voznesensky

Ivan, there are at least three official ways to make a loop in Python: by for/while, by iterables (map function/reduce function/etc.) and by recursion.

Syed Uzair Ahmad

Awesome man, Loved it

krill klev

Great Post. Here is a tutorial on python decorators that I liked the most - http://blog.apcelent.com/python-decorator-tutorial-with-example.html

Baoshan Gu

Great post. Thanks. In the adapter example, I believe udp_destination should be upd_logger.

Azhar

Yes, this should be udp_logger. I was thinking the same why udp_destination lol.

Andrei is a seasoned IT professional with much experience in a number of software technologies from low level programming to complex systems design and implementation. He has an extensive knowledge (Prince 2 and Agile) and experience in project management. He also has done software design, modeling, development, debugging, and optimization; worked in C#.NET, C, Python, PHP, UML, and UP.