Vlad Skvortsov's Blog

Tags
cyrillic ditrack gtd guitar mac music pdf phd postscript productivity programming projects python r russian shell terminal tex tips utf-8 wadcomblog

My name is Vlad Skvortsov, I'm a software engineer: it's my job, hobby and addiction.

My primary interests include high-performance, scalable, fault-tolerant distributed systems; server-side applications; information retrieval technologies; procedural aspects of software engineering process.

I work on several private and open-source projects, hacking in Python, Haskell, Erlang, Perl and C.

Guitar, hiking, ice hockey and other hobbies help me to balance my life.

My e-mail is vss@73rus.com.

Python: The First Impression

Jul 16 2006, 15:31 permalink

Recently I've decided to try using Python for my scripting. Python is mature (used by Subversion project -- and this means a lot for me, I consider Subversion development model quite "healthy"), has some Lispy features and comes preinstalled on Mac. Those alone are good reasons to give it a try!

Maintaining a bunch of old Perl projects, I can admit that it's not an easy thing to do partially because of the "write-only" syntax. Since there are "more than one way" to do it, every programmer does it his own way. Hence, in several iterations performed by different people (or even by one person in different time), the code becomes quite cryptic.

Python, on the other hand, somewhat enforces consistent style. From my perspective, it's a good thing: for about 8 years of Perl experience I still can't come up with my own consistent style (C required a couple of years for that to establish).

Also, Python seems to be moving in the Lisp direction and it's quite valuable for me: once hooked up to Lisp, I lack its features in common languages I use. Python has some elements of functional programming style (i.e. map() and reduce() functions, lambda expressions, etc) and this is quite exciting.

So I convinced Oleg Sharov (who I work on a couple of projects with), that we should switch DITrack to Python, since it might give us better maintainability in a long term, a chance to rewrite the system from scratch and a new experience learning another language. However, since we are done with DITrack development for the next release at this point and have started the release engineering process, the switch cannot happen right away. So, I needed a toy project to try Python and the blog engine behind this site became one.

I have to say that the learning curve for Python was quite gentle. I've spent about 2 hours reading online documentation and it took me 5 hours to write this simple blog engine from scratch still learning Python along the way. So, since it's less than a day worth of experience, this note should be considered as the real "first impression". For the downsides that I'm going to talk about, it may be just lack of knowledge, not the language deficiencies.

Things I Liked

The Python Library is quite comprehensive and that's great. Functions like makedirs() and str.strip() can be implemented easily, but it's a good thing that one doesn't have to implement them for each of one's small projects. It saves time, debugging effort and simplifies code migration from one project to another.

Another related thing that I liked about Python and its library is that the namespace is wisely used: calls to library functions visually stand out and do not create ambiguity with local names that tend to be short. Hence, there doesn't seem to be such thing as a namespace pollution.

I've already mentioned that str.strip() is quite handy: if I were paid a dime for each Perl code snippet I wrote that does the same thing, I'd probably have had quit my job by this time. Many languagues try to be orthogonal (which is a good thing) and do not include such routines into standard shipment, but as hard drives get cheaper and cheaper each month, this makes less and less sense. I'd be against of including libraries to access all kinds of databases into a standard language package (though, I'm not really sure about this one!), but all the basic routines that are used in almost every project -- they should be there for sure! This is like a code refactoring on large scale: it's a good thing to avoid code duplication by all reasonable means.

Paul Graham makes good points about brevity of programming languages. With respect to this, two things spring up in mind, which are nice in Python.

First is the abbreviation to change the direction of arrays indices: using negative values for that. I can't remember an occasion when I needed to use negative array indices (probably except for some math exercises back in university) and using a[-1] to get a hold of the last item of array looks more natural than Perl's $a[$#a].

The second thing is using square brackets to subscribe both arrays and dictionaries (hashes in Perl). Referencing array item and getting a hash mapping are the same things conceptually: why using different syntax for that?

Ability to use keyword arguments in function calls is another neat feature. I found myself often writing something like this in Perl anyway:


	my $rc = func ($arg1, $arg2,
		0,	# verbosity
		1	# errors are fatal
		);

... so having a concise (and non-mandatory!) syntax in Python is a win:
rc = func(arg1, arg2, verbosity = 0, fatal_errors = 1)
It also helps then the function interface changes (i.e. things won't break if another parameter is added to func signature).

Things I Didn't Quite Like

Though blocks defined by indentation are good in general, it's not handy to move them around the code and it's not easy to jump to either end of the block. I often use '%' command in Vi (Vim) that finds corresponding brace for the one that's under cursor, and since there are no block delimiters in Python, this technique obviously doesn't work here.

Assignments can't be mixed with expressions (if it's not something that I missed reading the documentation). Thus, I can't nicely read the file in Perl style:


	while (defined (my $str = <F>))
	{
		# Process line.
	}

Instead of this I have to write something like:

	while 1:
		str = f.readline()
		if not str: break

		# Process line.

Back to brevity topic again, one conceptual action is spread on 3 lines. It would be no problem at all with Lisp macros, but there is no such thing unfortunately.

The same claim also applies to exception handling. These statements tend to be pretty verbose and worsen code readability.

With general orientation to functional programming style, the sort and reverse methods of list objects are a bit irritating. They perform their actions in-place and do not return resulting object. Thus, instead of nice

print dict.keys().sort().reverse()
...I have to write something like

	keys = dict.keys()
	keys.sort()
	print keys.reverse()

Though, may be it's another thing that I missed and there is a better way.

One final thing that disappointed me a bit is packaged documentation. Perl is nice in this respect: you rarely need to go online to check function description. Just type perldoc -f func and you are all set: you've got a comprehensive reference. Now, with Python, typing, for example


	$ pydoc os.system

...gives you just 7 (seven!) lines of description:

Help on built-in function system in os:

os.system = system(...)
    system(command) -> exit_status
        
	    Execute the command (a string) in a subshell.

Yes, this is it! Compare with

15:21 [vss@claw] ~/notes > perldoc -f system | wc -l
      63

Random Notes

After programming in Python, I'm left with an impression that Python code looks more dense than Perl's one. This was rather subjective, though, and my measurements showed only a slight variation in numbers: my Python code density was about 22.0 characters per line and Perl's one is 20.0. However, the sample is not representative, I've written only about 350 lines in Python so far!

Conclusions

In general, I liked the language. It's easy to learn and fun to hack in. Enforced code indentation seems to play a good role in maintainability. Good library coverage allows to concentrate on solving problems without worrying about small side things. I admit that I've not yet dived into Python, but I've got some taste of that, and it was delicious.