During the last four weeks I was working on a legacy system written in python. Finally it started to feel productive: For the first two weeks I was trying to understand the system, tried to run it and its unit tests. During the second two weeks I actually got my hands dirty with code. It feels like I experienced both the ups and downs of this language.
Folti encouraged me to do this: I’m summarizing my first impressions here, although I’m still at the beginning of the learning curve.
There are many pages that explain why you should learn python. There are many resources for actually learning python too. This post is not about any of those. It only summarizes my first encounter with this language. The zeroth encounter happened a year ago: I went through the official python tutorial and implemented Conway’s Game Of Life.
The first and weirdest experience I had with python is that it uses white spaces to determine the beginning and the end of certain code blocks. After the first shock I realized that it means that in python I can simply skip those winks ‘;’ and mustaches ‘}’ my eyes are ignoring anyway.
Dynamic duck typing
Python is a dynamically duck typed language. That means no type-inference, no automatic checks for methods, nothing. You can’t just move a method from one class to another and then check which methods will the IDE underline for you. You can’t either just hit Ctrl-shift and let your IDE guess the rest for you.
On the other hand dynamic duck typing makes it easy to write test dummies. It makes generator expressions and list comprehension look just the same. Which, as Martin Odersky explained in progfun, can make DB queries look like list comprehensions – just like LINQ does.
Bottom line: dynamic duck typing is a shotgun, take care not to shoot yourself on the foot. No, wait! All the type-related errors make your application crash early. You will find and fix those bugs very soon. However, to make refactoring easier, I recommend short methods and good test coverage. No, wait again! Everybody recommends that for every language. Dynamic duck typing just makes it less avoidable.
Python lets you write short code. The concept of short and concise code is a red line that goes through every inch of the language design. Let’s see two examples for this:
Functional constructs are definitely one of these. Although Guido wanted to remove some of them, he fortunately changed his mind. I already compared Java and Scala regarding functional constructs – Java was 2-5 times as verbose as Scala.
Regexes show another example. If you need short code, you can go like this (it’s almost as short as in perl):
import re #... m = re.search('50.*Cent', '50 fucking Cents') m.group(0)
On the other hand if you want to compile a complex regex only once (which is almost as verbose as in java):
import re #... pattern = re.compile('50.*Cent') # ... m = pattern.search('I secretly love 50 cent') # ... m = pattern.search('Best friend drops a dime')
Long story short: python code basis are somehow much shorter than java code basis which implements the same thing. Hence you can write and understand python code faster.
When you work for a bigger company, usually you cannot just add a new library whenever it feels like OK. Sometimes there is a group of druids who call themselves architects and they decide which library you can use. Sometimes these druids call themselves security experts and they decide which libraries are secure enough to be copied into the internal network. Even in the most democratic teams you need to consult the colleagues if they already use another library for the same purpose. The longer it takes to add a lib to your project the more likely you are going to reimplement it.
Fortunately, python includes tons of libraries. So most of the time you don’t need to copy anything. Just import anti-gravity and you can fly.
One example: Recently I wrote some integration tests for our application. My boss suggested to use expect as it could communicate over telnet and it could check if the response was what we wanted to receive. I thought that before I learn yet another scripting language, I better check if python can communicate over telnet. Of course it has a convenient interface to do so. It has an xUnit implementation too so I had every tool I needed.
When writing python I’m still googling a lot. However, for most of the tasks I can quickly find a lib with an example snippet.
While writing the integration test tool, that awkward moment came when my boss asked me if my tool could do this or that. Usually, ‘this and that’ are requirements which weren’t specified, but, you know, it’s obvious that we need it. It’s a minor feature anyway, he would say.
Thanks to the libraries I could answer ‘this lib can do that, it just takes some time to learn how to configure it to do so’. No awkwardness this time: the testing tool was built on top of other libs designed, built, tested and enhanced by other people. Moreover, these libs works the same way they work in java. Once I learn what to import, I can instantly work with them. Maybe the elementtree was a bit strange at first, but it was easy to use anyway.
I was standing on shoulders of giants, I could say. But more importantly, python lib developers were standing on shoulders of other giants too. Hence the barrier between python and the rest of the world is really low. Whatever you have learned before moving to python, most likely you can use it. Unlike pascal, if a beginner learns things with python, she can use it later in her carrier.
Due to some security restrictions I used vim as my editor which is a big change after several years with Eclipse. Some of my observations aren’t necessarily true with a usual IDE. Please let me know if you’d correct anything.
Almost everything I want to do in python reminds me to some other language. Although I’m still relying on google a lot, I’m writing short and concise code quickly. Which feels productive.