Three months ago I changed jobs, and in the process switched from Java to Python. Here are the differences that have stood out for me since making the switch.
I have previously worked a bit in Ruby, but I had no experience with Python. I prepared by reading The Quick Python Book. However, whether you read a book or try it out by writing some code, it is not the same thing as working in it every day. The code base you work with is much bigger than some small examples you make yourself, and most of the code you encounter is written by somebody else. It is only when you immerse yourself in the new language and the code base that you learn “for real” what it is like to be working in that language. Here are the things, good and bad, that I have noticed the most so far.
Tuples. A tuple is simply a grouping of elements that can be of the same or different types (like a struct in C). For example, a 3-element tuple describing a book could be (title, author, number_of_pages). They correspond to how I naturally think about data, and I find them useful all the time.
Returning multiple values. In Python, a function or a method can return multiple values easily be returning a tuple. Combining this with tuple unpacking, you can write code like this:
max, min, avg = summarize(source)
This is also very natural and useful. In Java, I sometimes created simple result classes (just containers for the different variables) and returned those when I needed to return multiple values. But it took some effort, which meant that I didn’t use it as much as I would have liked. In Python, where this is dead simple, I find that I return multiple values a lot.
Functions as arguments. In Python, functions and methods are first class objects. This means for example that they can be passed in as arguments to other functions and methods. In my opinion, this is much cleaner and easier than the Java way with interfaces (often combined with ugly anonymous implementations). Being first class objects means that they can be returned as the result of functions as well, but so far I have not had a use for that.
Stand-alone functions. In Python, you can define functions that stand by themselves, unlike in Java, where they always have to belong to a class. In Java I frequently used static methods for “functional” tasks (functions that didn’t require any state, but instead only depended on the arguments passed in). In Python, it feels better to simply create these as loose functions, without having to connect them to a class.
Compact code. The code I write in Python feels more compact (fewer lines) than the corresponding code in Java. Partly this is because there are many operations that are naturally expressed as creation and transformation of lists (which Python has great support for), partly it is because there is almost no boiler-plate code in Python, and partly it is due to the use of indentation instead of braces for delimiting blocks.
Odds and ends. There are a few other features that were pleasant surprises, for example named arguments and default arguments, the built-in function enumerate, flexible string quoting (double quote or single quote, which makes it very easy to write a string containing quotation marks – just surround the string in the other kind of quotation marks). I also found out that you can use the import-statement within a function, to make the dependency local to the function.
No Static Types (1). The biggest drawback for me is that there is no type information when reading code. In Java, when I saw a new function and tried to understand what it did, I almost always looked at the types of the arguments and return value to get a sense of what it did. In Python, it is much harder. It takes a lot more digging to find out what a function does in Python. The quote from Linus Torvalds about the importance of data structures comes to mind. It is not that the data structures aren’t there, it is just that it is harder to see what they are in Python compared to in Java.
No Static Types (2). The other consequence of the dynamic typing in Python is that the “find usage” feature in the IDE is not as useful. I am using PyCharm for Python, and used IntelliJ IDEA for Java. In Java, I used “find usage” a lot to find out where a method is called from, where a class is used etc. In PyCharm the accuracy is (naturally) worse – often there are many false positives for usage, unless the name of the function is unique. So it is basically back to grep:ing the code base for a given string (like in my C++ days).
So which is better? For me, this is not an important question. I am not a Java-programmer, or a Python-programmer. I am a programmer, period. There are differences, but Python and Java have more in common than what sets them apart. Fundamentally, programming is about breaking a problem down, and then using elementary operations, conditions and iterations to solve it. The mechanics may vary, but the core is the same.
It is fun to learn and use a new language. It is interesting to to compare it to other languages. Then you can use its strengths and work around its weaknesses. In the end though, programming is programming, regardless of the language. I was happy to program in Java, and I am happy to program in Python. But mostly I am just happy to program.