Question

I've got a background in Python (though entirely self-taught, so I might have some bad habits or misconceptions), and I'm trying to learn Ruby to broaden my scope.

I was reading through some comparisons, and saw a lot of assertions that "Python can't do metaprogramming" (or, less inflammatorily, "Python can't do metaprogramming so simply as Ruby"). So I went away and quickly read about metaprogramming, and came away with the impression that it is, basically, editing the methods/behaviour of your classes/objects during runtime (please do correct me if I'm incorrect!).

I was under the impression that, since Python is dynamic, that shouldn't be a problem. However, I ran the following test code, which didn't give the response I expected:

>>> class foo:
...     def make_hello_method(self):
...             def hello(obj):
...                     print 'hello'
...             self.hello = hello
...
>>> f = foo()
>>> f.hello()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: foo instance has no attribute 'hello'
>>> f.make_hello_method()
>>> f.hello()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: hello() takes exactly 1 argument (0 given)

I was under the impression that every method of an object was automatically passed the object itself as the first argument (hence the constant requirements to define object methods as (self, [...])). How come f isn't being passed to hello()?

Was it helpful?

Solution

You need to make it an instancemethod. There's a class to do that in the types module. This will work:

self.hello = types.MethodType(hello, self)

OTHER TIPS

Seeing as you are using Python 2, you could use the new module to make this work:

self.hello = new.instancemethod(hello, self, foo)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top