Scherprechter neemt poolshoogte
(I decided to limit myself to one rant a year. This is it.)
Just saw this blog post (via Hacker News): Dear Python. In it, the author lists a number of complaints he has about Python.
There is so much wrong with this article that it’s like shooting fish in a barrel.
First of all, the post seems to imply that Python started out great, but then added inferior copies of features found in other languages:
But then you got jealous of the big players. You saw that others had things you didn’t have and you wanted to compete in a game that you were never destined to play. And who could blame you? The megaliths in the crowd like Java and c++ were beginning to overshadow the small guys and were even starting to overtake some of the oldest and wisest players: c, Fortran, lisp. What did they have in common? Objects.
Objects have been around since the very first public release of Python (0.9.1). They were not added because of “object envy”. Hell, Java didn’t even exist when Python first came out.
But you weren’t ecstatic about objects. You didn’t really like them and you didn’t trust them. So you decided to only give them a little. You cut corners. You made objects but you made them hard to use. That was a mistake.
That’s another odd argument… IMHO, Python’s objects are *much* easier to use than, say, Java’s, or C++’s, where you have to micromanage access (public? private? protected?), write (often superfluous) getters and setters, and deal with such niceties as as “final” classes, checked exceptions, abstract classes, interfaces, etc. In Python, I can just write the class, stick in it whatever I want, *use* it however I want, and move on.
There is no encapsulation. There are three tiers to OO. One of them is encapsulation. Having OO without encapsulation is about as nice as sawing a leg off a three legged stool. I can hear you yelling, “That third leg is completely unnecessary. We’re all consenting adults here. Just balance, like this…” *crash*.
I am assuming that by “encapsulation” the author means “data hiding”. Python’s philosophy here is that in order to separate interface from implementation, data hiding is not necessary. That’s where the “consenting adults” idea comes from; you are *supposed* to talk to the object using its interface (methods or properties, usually), but if you really have to, you can easily access any attribute. There are ways to make this harder, but (again, IMHO) they are not very Pythonic.
Also, the notion of “three tiers to OO” really depend on which definition you go by. Java, C++, C# and their ilk are neither the first word in OO, nor the last. Languages like Smalltalk, Self and Io have (sometimes radically) different ideas about what objects are and how they are handled.
Then, libraries:
However, these libraries are inherently static. This means that if the library doesn’t do what you want it to, you are screwed. There is no diagnosing or fixing errors in the library. If they happen, pack up and try a different language.
I’m not sure in what sense Python’s standard library is “static”… there are a few built-in modules written in C, but most of them are in pure Python, and the source code is readily available. You could change them if you must, but a better approach would be to subclass them and replace the offending features/bugs. (Note that there are no “final” classes and private attributes to get in your way here. :-)
(The httplib problem mentioned looks like it can be solved by setting a proper timeout value, by the way. I’ve written several web crawlers in Python, and never encountered this issue.)
Then there’s the tired old “explicit self” argument again:
[...] But sadly, this is exactly how python is. It doesn’t really take care of anything for you. You have to have “this” as the first argument to every function in a class. Once in a function, you have to use “this” to access any variables or other functions.
I’ve written about this before (in 2003!) so I’ll just links to those posts here, rather than repeating it:
And here’s what Guido himself has to say about it: Why explicit self has to stay.
The Java way is better. The implied this is easy to understand. Some IDE’s even highlight the class variables with a different color than the local variables, allowing an easy distinction. In the end you save tons of characters by having an implied “this”.
The implied this (in a method’s argument list) may be easier, but Java gets away with this because it doesn’t have actual functions. Python, as a multi-paradigm (god I hate that word :) language, does, and in fact methods are really just functions that you stick in a class.
Also, the “tons of characters” you save don’t mean much, when a typical Java method definition starts with stuff like “public static final void …”!
To add insult to injury, python has no explicit support for member definition. A class’s members are created by setting them equal to something. There is no way to explicitly define them in the class definition. Anybody, anywhere, can add (or remove) members variables from a given object. Classes in Python are more like dictionary objects with functions attached than classes.
Um, yes, the lack of declarations is one of the factors that makes Python code shorter and more flexible. And indeed a class (or an object) is much like a dictionary with some special rules added. Hint: the same is true for languages like C++ and Java, except they hide that dictionary behind a ton of cruft, so you won’t notice it as much.
I agree that removing attributes from a class or object generally isn’t a good idea, but then again this doesn’t happen a lot, unless in special cases.
After much frustration at using your broken OO, I decided to give it a rest. Maybe python would make more sense if I just treated it as a flat procedural language. Then I noticed lambdas. [...] They can only be one line.
Agreed, Python’s lambda sucks compared to functional languages (and even Ruby). However, it was intended as a shorthand for simple functions, not as a full-fledged alternative to def.
Python, you are just like the little kid Peter. You see something others have, decide you must have it, and then you just stick it somewhere. To become a better language, you must outgrow this little kid copy cat phase.
If you want objects, implement objects all the way. This includes things like encapsulation and variable definitions. But if you don’t want objects, then don’t implement them at all. It is no help for anybody when you implement something that you don’t want people to use.
This really makes no sense. “Implement OO like Java, or don’t implement it at all”. Gee, go tell that to the authors of Smalltalk, Io, Self, CLOS, Simula, OCaml, even Ruby. Again, what “object oriented” means isn’t written in stone, and Java’s implementation of it certainly isn’t the gold standard. I don’t think the original inventors of OO intended the language to get in your way constantly, for starters.
~
Granted, Python has its problems. Over the years, these have become more clear to me. I am mostly infatuated with ultra-dynamic and/or functional languages at the moment (but that is a different story…). I don’t like the join method on strings, the fact that we have classmethods/staticmethods/etc now and all that drivel, and I would have liked the language to be more flexible, for example. But all of these criticisms are fairly minor. Python is still the language I am most comfortable with, and the language I reach for first in many cases.
So, yeah, I can understand people’s frustrations with the language, but this is just completely wrong. And what is this !@#$ about Python being a copycat language?! Yes, some features were borrowed from other languages — list comprehensions come to mind — but there aren’t that many examples of it, and it’s hardly the only language that does this. In fact, if I’m not mistaken, Java, C++ and C# all have grown features borrowed from dynamic languages… except such features tend to have limited use in a environment that is statically typed.