I had a program fail on me today because the following didn't work as I expected:
class C:
... def f(self): ... pass ...
c = C() m = c.f m is c.f
False
I would have expected that if I set a variable equal to a bound method, that variable, for all intents and purposes, *is* that bound method, especially since I hadn't changed or deleted anything on the class or its instance.
The same thing happens when attempting to compare an unbound method with a variable name bound to that unbound method:
M = C.f M is C.f
False
If I were to guess what is going on here, I would say that the expression
c.f invokes a descriptor that manufactures a brand new "method object" each
time.
Yes, I believe that's the case. See Martelli's recent 'Black Magic' PyCon presentation for some details of what's going on, but IIRC, the essence is that a bound method is produced by calling __get__ on the function, with the class/instance as the argument
The problem is, this is non-intuitive (to me) and prevented me from
doing something I thought was useful.
Agreed that: >>> class C(object): ... def f(self):pass ... >>> C.f is C.f False
is surprising
My use case is deferring operations till later, by placing tuples of a method and its arguments in a list to be processed at some future time, but doing some special-case processing only for certain methods:
deferred = [] ... deferred.append((c.f, ('abc', 123)))
...
for method, params in deferred: method(*params) if method is c.f: # handle a special case
But I can't do that special-case handling this way, I have to resort to some other means to identify a method, "method is c.f" is always False. Which seems strange to me.
Another workaround is to compare method.im_func which does pass the identity test ...
If I complain about this, would I get any sympathy? ;)
Sympathy, sure ;-)
Michael
-- http://mail.python.org/mailman/listinfo/python-list