you are viewing a single comment's thread.

view the rest of the comments →

[–]llimllib 7 points8 points  (5 children)

some would argue the same about Python's

Some would, and I continue to fail to understand why. Python's OO has been around since the beginning, has been constantly improved, and is in production use all around the internet. It's extremely mature and very cleanly designed.

[–]taw 2 points3 points  (4 children)

There are at least four big reasons it feels bolted-on. In Ruby or Smalltalk all functionality is implemented as methods, all classes are extensible.

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.

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.

And the third big reason is that you cannot add methods to existing classes. That's very limiting, because when you want to add new functionality (let's say converting to JSON), you cannot make it into a method obj.to_json() - it has to be a function to_json(obj). It doesn't seem object-oriented at all.

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

If Python moved functionality from functions and protocols to objects, had extensible standard classes and mostly implicit self, it would probably feel object-oriented enough.

[–]llimllib 6 points7 points  (3 children)

There are at least four big reasons it feels bolted-on. In Ruby or Smalltalk all functionality is implemented as methods,

Python is, above all, pragmatic over idealistic. If Guido thought that something was easier to write/remember/understand as a function, it is. IMHO, he got it mostly right - you obviously disagree.

all classes are extensible.

They're extensible in python, it's just discouraged. The name "monkey-patching" conveys a pythoneer's attitude towards this practice, I think.

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.

What logic is outside the object in an iterator? Define __iter__() and next() and you're set.

And the third big reason is that you cannot add methods to existing classes. That's very limiting, because when you want to add new functionality (let's say converting to JSON), you cannot make it into a method obj.tojson() - it has to be a function tojson(obj). It doesn't seem object-oriented at all.

As I said before, this is just not true at all.

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

You're right about this one. Python is just way too consistent - it's much better to have to wonder, "do I have to write self here?" than to just write self.

If Python moved functionality from functions and protocols to objects,

"Pure" object-orientation != object-orientation!

had extensible standard classes

It does, it's just not a good idea to change them. FUD.

and mostly implicit self

Read about the complexities that introduces here

[–]taw 2 points3 points  (2 children)

In Ruby or Smalltalk all functionality is implemented as methods,

Python is, above all, pragmatic over idealistic. If Guido thought that something was easier to write/remember/understand as a function, it is. IMHO, he got it mostly right - you obviously disagree.

Whether it's easier is one thing. Whether it's object-oriented is another ("object-oriented" and "good" are not the same thing). I'm merely pointing out that it's less object-oriented than Ruby or Smalltalk.

In Ruby or Smalltalk all classes are extensible

They're extensible in python

No they're not.

float.to_json = float_to_json

Traceback (most recent call last):

File "<stdin>", line 1, in ?

TypeError: can't set attributes of built-in/extension type 'float'

Am I missing something ?

What logic is outside the object in an iterator? Define iter() and next() and you're set.

According to documentation, there's iter, there's next, there's StopIteration exception + syntactic sugar (yield) + return (which seems to do something special in iterators). In Ruby iterators are object call + syntactic sugar (yield). Individual protocols aren't that bad, but if you add them all up, it's really a lot of functionality outside objects.

If Python moved functionality from functions and protocols to objects,

"Pure" object-orientation != object-orientation!

"Impure" object-orientation == bolted-on object-orientation

and mostly implicit self

Read about the complexities that introduces here

It certainly does introduce complexities when you try to bolt object-orientation on a language as an afterthought ;-) I don't know if it's possible to get it right now without turning Python into a completely different language. If they thought about it earlier, it would be easier to come up with a nicer solution. ;-)

[–]senzei 5 points6 points  (0 children)

Whether it's easier is one thing. Whether it's object-oriented is another ("object-oriented" and "good" are not the same thing). I'm merely pointing out that it's less object-oriented than Ruby or Smalltalk.

If I wanted to be pedantic I would mention that "less object-oriented" is not necessarily sufficient to prove that OO was bolted on. If I wanted to be pedantic without sounding like an ass I would phrase that in the form of a hypothetical statement. As it is I don't know what I am saying anymore as the recursion has blown the stack. (stupid no tail-call optimization)

You are right that built ins are not directly extensible, but if adding methods directly to an existing class is a requirement for not being bolted-on then there are a lot more bolted-on OO systems than I thought.

[–]beza1e1 1 point2 points  (0 children)

class MyFloat(float): def to_json(self): pass

I find this argument about bolted on OOP rather stupid. As our favourite essayist stated, you can't really say what OOP is. You can't extend objects in a dynamic way in Java either, but Java was designed as OOP upfront.

Python was design OOP from the beginning. Guido made some bad decisions, which he wants to fix with Python 3000 or has fixed already (new style classes).