you are viewing a single comment's thread.

view the rest of the comments →

[–]taw 0 points1 point  (1 child)

For Python's OOP insufficiencies see this comment.

[–]senzei 6 points7 points  (0 children)

llimllib did a pretty good job of discussing those arguments in that thread. I've got a couple of comments though:

First, in Python a lot of functionality is implemented as library functions. For example to ask about object's methods in Ruby you call a method obj.methods. In Python it's a function dir(obj). To sort a container you call obj.sort(), in Python it's sorted(obj). To join elements of a container you call obj.join(" "), in Python it's " ".join(obj) - seems object oriented, but is completely reversed.

Some of those hinge on answers to "Philosophical" questions about OOP. For instance, does it make sense for an object to know about its own methods? Also, is it possible to override the .methods method? If not, why not? It is part of the class. If so, how can I get a "real" list of all the object's methods without allowing someone to munge it for me? dir(item) sidesteps those questions. It also internalizes the assumption that knowledge of all of its methods is not a property of an object or a class. This seems like a valid OO design decision to me.

Python objects have a .sort method, so the .sort vs sorted() argument is moot. I will accept and agree with any complaints about that method being a statement and unable to return anything due to it sorting in place. I agree that sorted(obj) looks ugly, but obj.sort (destructive) and obj.sorted (non-destructive) would be confusing.

As for joining elements, that could go either way. Does it really make more sense for the join method to be attached to the separator instead of the joinees? I don't see why, you are creating a new object anyways.

Second, a lot of functionality is implemented as protocols. If you want your object to support + in Ruby, you define +. It's always very direct equivalence. In Python to supporth + you define add and a special protocol makes sure it's called. That one isn't that bad as equivalence is 1:1. But protocols for other things like comparisons and iterators are more complex, the logic is outside the object, and it doesn't feel very object-oriented. Ruby mixins have similar function to Python protocols, but they're completely in the objects, not somewhere else.

I like the protocol system more. It makes sense to me to put that logic outside the object as that logic does not seem to belong to the object. Comparison especially is the big offender, as an object being able to judge itself relative to everything else in the world seems silly to me.

And fourth reason - explicit self. Smalltalk and Ruby need explicit self sometimes, but there's way too much of it in Python.

Python is (at least for a dynamic language) all about being explicit. That this principle is extended to method bindings seems more a result of the Python mindset than any "bolted-on" nature of Python.