Post #114,943
8/22/03 2:38:42 PM
|

MOO/FOO and Python
I was thinking about Message vs Function OO (see [link|http://z.iwethey.org/forums/render/content/show?contentid=110693|http://z.iwethey.org...?contentid=110693]) and where Python falls on the chart. My Python experience is limited, so ...
Originally, I would have guessed that Python and Ruby fell in the same category because there are a lot of similarities between the two. However, in thinking about the issue some more, I realized there is a very basic difference. In Ruby, "x.y" means send the "y" message to the "x" object. In Python it is a structure selector, so "x.y" returns a function that is called when "()" is applied.
So the Python semantics seem to be "function" oriented. Does that make it a FOO language? Can you capture a message as you can in Smalltalk/Ruby?
-- -- Jim Weirich jweirich@one.net [link|http://onestepback.org|http://onestepback.org] --------------------------------------------------------------------- "Beware of bugs in the above code; I have only proved it correct, not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)
|
Post #114,944
8/22/03 2:41:18 PM
|

Having done this before...
Yes... you can always move the original method on a class to a different, shadowed name. Then create your own method of the same name that "does something", perhaps including calling the original.
Not as elegant as Smalltalk/Obj C, I think, but at least you can do it. This is 1.5.2 knowledge; 2.X may have a better technique.
Regards,
-scott anderson
"Welcome to Rivendell, Mr. Anderson..."
|
Post #114,955
8/22/03 3:18:41 PM
|

I'm not sure that's what I mean
So let me be more specific ... Can you create a class that reports what methods have been called on it, without knowing upfront what the methods will be? For example e = Echo.new\n e.hi # prints: "Someone called hi() on me."\n e.calc(1,2) # prints: "Someone called calc(1,2) on me." Here's the Ruby code for this class Echo\n def method_missing(sym, *args)\n puts "Someone called #{sym}(#{args.join(',')}) on me."\n end\n end
-- -- Jim Weirich jweirich@one.net [link|http://onestepback.org|http://onestepback.org] --------------------------------------------------------------------- "Beware of bugs in the above code; I have only proved it correct, not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)
|
Post #114,961
8/22/03 4:15:08 PM
|

Like this:
\nclass UpperClassTwit(object):\n def __getattribute__(self, name):\n print 'trying %r.%s' % (self, name)\n try:\n parrot = object.__getattribute__(self, name)\n except:\n print 'not found: %r.%s' % (self, name)\n return self.hidey_ho\n\n return parrot\n\n def hidey_ho(self):\n print 'oog'\n\nf = UpperClassTwit()\n\nf.garble()\n Running this yields: \n>>> ## working on region in file /usr/tmp/python-1260iBu...\ntrying <__main__.UpperClassTwit object at 0x81de63c>.garble\nnot found: <__main__.UpperClassTwit object at 0x81de63c>.garble\ntrying <__main__.UpperClassTwit object at 0x81de63c>.hidey_ho\noog\n>>> \n
Regards,
-scott anderson
"Welcome to Rivendell, Mr. Anderson..."
|
Post #114,963
8/22/03 4:16:04 PM
|

:) I haven't "gone meta" enough yet, I see...
"There's a set of rules that anything that was in the world when you were born is normal and natural. Anything invented between when you were 15 and 35 is new and revolutionary and exciting, and you'll probably get a career in it. Anything invented after you're 35 is against the natural order of things." Douglas Adams
|
Post #114,983
8/22/03 5:52:21 PM
|

I came up with this ...
Here's what works ... class BoundCall:\n def __init__(self, name):\n self.name = name\n def __call__(self, *args):\n print 'Calling %s%s on me' % (self.name, str(args))\n\nclass Echo(object):\n def __getattribute__(self, name):\n return BoundCall(name)\n This is pretty close to what I was thinking. There might be a few differences w.r.t. predefined methods in Object, but that's ok. I had to download Python 2.3 for this to work, so I guess that makes pre-2.3 python a FOO language and post-2.3 MOO. Thanks.
-- -- Jim Weirich jweirich@one.net [link|http://onestepback.org|http://onestepback.org] --------------------------------------------------------------------- "Beware of bugs in the above code; I have only proved it correct, not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)
|
Post #114,984
8/22/03 6:02:50 PM
|

I ran mine in 2.2.3, FYI
I think __call__ is new in 2.3.
Regards,
-scott anderson
"Welcome to Rivendell, Mr. Anderson..."
|
Post #115,043
8/23/03 8:25:55 AM
|

My 2.2 is evidently broken
I thought __call__ had been available for some time, but what do I know.
I discovered my python2.2 installation is broken. It was silently swallowing the script without any output. Turns out that it is not the script's problem, 2.2 is is silently swallowing everything. I should probably just uninstall it (why does my system have 3 versions of python anyways).
-- -- Jim Weirich jweirich@one.net [link|http://onestepback.org|http://onestepback.org] --------------------------------------------------------------------- "Beware of bugs in the above code; I have only proved it correct, not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)
|
Post #114,962
8/22/03 4:15:17 PM
|

AFAICT that hinges on method_missing...
..which also AFAIK Python doesn't have.
So, no, Python is not message-oriented in that sense. However, it's trivial to simulate, since you *can* add methods and attributes on the fly to a Python class, and enumerate a class' methods/attributes/whatever.
"There's a set of rules that anything that was in the world when you were born is normal and natural. Anything invented between when you were 15 and 35 is new and revolutionary and exciting, and you'll probably get a career in it. Anything invented after you're 35 is against the natural order of things." Douglas Adams
|
Post #114,965
8/22/03 4:21:57 PM
|

You could also do this:
Create a base class that defined __get_attribute__ as I've done above, which then calls attribute_missing() if the attribute isn't there. To differentiate between a method and a member request, you can use the behavior that __getattr__ is called for members only, while __get_attribute__ is called for both members and methods.
Regards,
-scott anderson
"Welcome to Rivendell, Mr. Anderson..."
|
Post #115,185
8/24/03 3:13:15 PM
|

Coming at it from the other way
In Python, one can add functions to a class on the fly: \n>>> class MyClass:\n... \tpass\n... \n>>> a = MyClass()\n>>> a.test()\nTraceback (most recent call last):\n File "<interactive input>", line 1, in ?\nAttributeError: MyClass instance has no attribute 'test'\n>>> def myMethod(self, name):\n... \tprint "Hi from " + name\n... \t\n>>> myMethod(a, "stand alone")\nHi from stand alone\n>>> MyClass.test = myMethod \n>>> a.test("a class")\nHi from a class\n Can this be done in a method oriented language like Ruby? Regards, John
|
Post #115,325
8/25/03 4:44:26 PM
|

Adding new methods in Ruby
Classes are always open in Ruby. New methods can be added at any time. # Create a new class\n class MyClass\n end\n\n # Create an instance\n a = MyClass.new\n\n # Send a message for a non-existent method\n a.f # => NoMethodError: undefined method `f' for #<MyClass:0x1a1810>\n\n # Open the class and add a new method\n class MyClass\n def f(name)\n puts "Hi from #{name}"\n end\n end\n\n # Now the instance will recognize the message\n a.f("a class") # => "hi from a class"
-- -- Jim Weirich jweirich@one.net [link|http://onestepback.org|http://onestepback.org] --------------------------------------------------------------------- "Beware of bugs in the above code; I have only proved it correct, not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)
|