Saying hello to Python: observations from a newbie
The last few weeks i’ve been dabbling around with Python. I’m busy doing some experiments with OpenCV, and because it has Python bindings it seemed like a good excuse to dive a little bit more into Python.
Here are some of my observations, from somebody with a background in mostly frontend jobs, usually Javascript/Node.js and/or PHP.
Good
- Python is mostly readable after a few months of not looking at it. I know the language is designed to do this, but it’s still pretty amazing when you dig up a script from a few months back and you don’t feel like reading Finnegan’s Wake.
- Things usually do what they should do. There’s little confusion over methods. Getting the contents of a file is simply
f = open("file.json").read()
- The module system is easy enough to not overload with boilerplate when writing simple scripts, but powerful enough for writing large applications. It’s even easier than how Node.js does it, no module.exports, simply define functions, import the module and Bob’s your uncle.
- It’s a small thing, but it pleases me that writing
def
is shorter thanfunction
in PHP/Javascript. - Package support is a lot better, it’s like the Mac app rule: packages simply seem better, especially if you compare it to the awfulness that is NPM modules (esp. in regards to documentation). Most packages seem written with the fact in mind that other people than the original coder are going to use it.
- Python seems to strike a nice balance again between readability and longevity in the method names. It’s simply
file.read
,sys.exit
. It’s a lot better than the confusing short PHP method names (srtolower
vsnl2br
) and the boring long Java methods (FileProcessingDecorator
,readMultipleLineStrategy
or whatever). - Even though i’ve read otherwise, for most of my uses, Python is fast enough.
- Googling for common questions virtually always leads to a relevant, well written StackOverflow post.
- Debugging seems easy. Most errors are readable and you never get the awful ‘white page of death’ like in PHP.
- The internal
help
method is awesome, especially when combined with the powerful REPL. I love the fact thatimport mymodule
even works in the REPL and you can do little tests and experiments.
Could be better
- The documentation is not very good, especially compared to PHP. Reading the Python docs feels more like reading a language spec than something that helps you solve problems. Especially, there’s a lack of simple and clear examples. If i want to know something i usually Google something and end up at StackOverflow. That shouldn’t be the case. Even the Node.js docs seem more readable.
Here’s an example. Let’s say i want to know how to do the Python equivalent of PHP’s foreach
. The docs about the for statement say this:
The for statement is used to iterate over the elements of a sequence (such as a string, tuple or list) or other iterable object:
for_stmt ::= "for" target_list "in" expression_list ":" suite
["else" ":" suite]
Right, so what does that mean? What’s ::=? What’s an ‘expression list’?
The expression list is evaluated once; it should yield an iterable object. An iterator is created for the result of the expression_list. The suite is then executed once for each item provided by the iterator, in the order of ascending indices.
“Ascending indices”? “Suite”? This might be clear for a CI professor, but it’s not for the mere mortals that read the docs and want to get stuff done.
And after reading this section i still don’t know how to do foreach in Python :(
Nice that the search works on the offline download though.
- ‘Variable hiding’ is confusing. I realise you shouldn’t be using
def
orif
as a variable name, but because of ‘variable shadowing’ stuff liketype
orid
might also not your best choice for a variable name, even though it makes a lot of sense. The convention seems to be to put an underscore after the variable (type_
orid_
) but that looks like a clunky hack. - Adding to that, having modules in a directory that have the same name as a module give really weird error messages. For example, try naming a module
stat.py
and then runpython
. lambda
syntax seems somewhat…funny. Why can’t we have multiple-line lambda’s (yes, i know that’s why). For now, defining a function in a function and returning that feels like a kludge. Especially when doing anything complex with map or filter this is irritating.- Why can’t we have dot access to members of a dict? Writing dict[“instruments”][“guitar”] instead of dict.instruments.guitar because boring pretty fast. Furthermore, the difference between dicts, tuples, objects and what works as an options object in a function is confusing.
- pip seems to do its job, but i’m still a little confused by how it works. What if i need a different version of a module than the one installed globally? Composer and NPM seem to handle this better.
- It’s not as easy as PHP to write a simple webpage, although Flask makes it as easy as writing an Express.js app.
- I should probably write something about Python 3 here. But on the other side, i haven’t really had any trouble with it. I guess. I don’t even know which version of Python i’m running. That might be something positive as well, i can’t count the number of times i’ve been cursing because a server didn’t have PHP 5.3 installed and i couldn’t use anonymous closures.
- Why can’t we have json.loads(“file.json”)? The
indent
parameter injson.dumps
is awesome though.
So, that’s my list. What are the things you like and hate about Python?
If you like this post, why not give a vote on Hacker News?
Nils Breunese
Python is ok, but I really wouldn’t know why I’d want to use it instead of Groovy, which is still the best dynamic language I know. Very consistent API (much more so than Python!), a REPL (groovysh), closures, optional typing, it’s got it all!
It has ‘def’, it has XmlSlurper/JsonSlurper/ConfigSlurper (look them up!), very neat collections API, support for functional programming, great builder syntax, very suitable for domain specific languages, reading a file into a string can be as simple as “new File(‘file.json’).text”, good IDE support, allows variable substitution in strings (which is a lot nicer than Python’s “Hello %s” % name), it has the *awesome* safe navigation operator (“?.”, go read about it!), the elvis operator (“?:”) and the star-dot operator to perform a function on each value in a collection (“*.”), built-in support for getting dependencies from repositories via Grape (yes, this is way better than what Python offers), mrhaki has awesome concise Groovy Goodness articles with tips and tricks and if you’re looking for a full stack web framework Grails is great (mrhaki has articles for that as well). And you can use the wealth of Java libraries without having to ever learn to code Java. I could go on for a while…
Every Python script I ever wrote I wanted to rewrite in Groovy the moment it got a little larger than 1-2 pages of code. And I often did. I’d really want to suggest Groovy to everyone considering learning Python. It’s a comparable language in lots of ways, but just a little better in lots of areas IMHO.
Groovy differences from Python: http://groovy.codehaus.org/Differences+from+Python
Getting started guide: http://groovy.codehaus.org/Getting+Started+Guide
User guide: http://groovy.codehaus.org/User+Guide
For those new to both Java and Groovy (en Java hoef je dus echt niet te kennen of leren): http://groovy.codehaus.org/For+those+new+to+both+Java+and+Groovy
Nils Breunese
Python’s package manager situation has always been a mess. There’s easy_install (which has no uninstall!) and pip (both easy_install and pip use PyPI) and since neither is really usable you have to add virtualenv to the mix to somewhat deal with this mess and create isolated Python environments.
“Python Packaging: Hate, hate, hate everywhere”: http://lucumr.pocoo.org/2012/6/22/hate-hate-hate-everywhere/
Really people, just use Groovy. :)
Andre Engels
Well, as you say, the readability of Python is a big plus in my opinion, as is the simplicity that a well-programmed Python program often has.
A great favorite of mine are list comprehensions. If p is some list of numbers, then a list consisting of the squares of the odd numbers in the list is simply “[x*x for x in p if x%2 == 1]”. Simple and powerful (and a more readable than attempts in other languages to include the same construct).
And regarding foreach: The Python equivalent of “foreach (A as $x)” is simply “for x in A”.
Nils Breunese
> If p is some list of numbers, then a list consisting of the squares of the odd
> numbers in the list is simply “[x*x for x in p if x%2 == 1]“.
It might be a matter of taste, but I don’t think that’s too easy to read. I get it, but I rather read something like this in Groovy using chained method calls and closures instead of a list comprehension:
range = 1..10
range.findAll { it % 2 == 1 }.collect{ it ** 2 }
===> [1, 9, 25, 49, 81]
Hans van der Graaf
I learned Python because I wanted to program against Google App Engine. It takes some time to learn it. StackOverflow is indeed a good information source. After a while Python feels very comfortable, allthough I had to rewrite the code several times to make it more efficient. So the biggest problem I had was that it wasn’t directly clear what is efficient code in Python.