mk a écrit :
(snip)
Sorry, no time to get into details now - but I can at least provide a
couple hints.
The first point is that, to override a method on an _instance_, you have
to provide a method object, not a plain function - remember that the
descriptor protocol is only invoked on _class_ attributes, not on
instance attributes.
class Foo(object):
def bar(self):
print "the original bar"
def mybar(self):
print "mybar"
>>> f = Foo()
>>> f.bar = mybar
>>> f.bar()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/tmp/python-1287O_i.py", line 32, in <module>
f.bar()
TypeError: mybar() takes exactly 1 argument (0 given)
>>> type(f.bar)
<type 'function'>
>>> f.bar is mybar
True
>>> f.bar(f)
mybar
As you see, "bar" is here resolved as an ordinary instance attribute -
so here it evals to the "mybar" function object. If you want it to be a
method object, you do have to invoke the descriptor protocol manually:
>>> f.bar = mybar.__get__(f, type(f))
>>> f.bar
<bound method Foo.mybar of <__main__.Foo object at 0xb7e16b0c>>
>>> f.bar()
mybar
Or alternatively, you can use the types module:
>>> import types
>>> f.bar = types.MethodType(mybar, f, type(f))
>>> f.bar
<bound method Foo.mybar of <__main__.Foo object at 0xb7e16b0c>>
>>> f.bar()
mybar
Second point is that the descriptor protocol is invoked on each and
every lookup. So when it comes to function class attributes, you get a
new method object each time:
>>> f = Foo()
>>> m1 = f.bar
>>> m1
<bound method Foo.bar of <__main__.Foo object at 0xb7cb522c>>
>>> m2 = f.bar
>>> m2
<bound method Foo.bar of <__main__.Foo object at 0xb7cb522c>>
>>> id(m1)
3084861188L
>>> id(m2)
3083656564L
>>> m1 is m2
False
>>>
I think this should help you understand why your code doesn't work as
you assumed it would !-)
PS : as a side note, a common optimization trick is to "short-circuit"
the whole lookup / descriptor mechanism when you have to call the same
method of the same object in a loop:
l = []
append = l.append
for i in xrange(100):
append(i)
print l
HTH
--
http://mail.python.org/mailman/listinfo/python-list