Reference to self not passed to member function
Bengt Richter
bokr at oz.net
Fri May 6 23:00:54 EDT 2005
On Sat, 7 May 2005 01:06:31 +0200, "Fredrik Lundh" <fredrik at pythonware.com> wrote:
>James Stroud wrote:
>
>> I did this:
>>
>> py> class bob(object):
>> ... def __init__(self,**kwargs):
>> ... for fname,func in kwargs.items():
>> ... setattr(self, fname, lambda *args : func(*args))
>> ...
>> py> def doit():
>> ... print "wuzzup?"
>> ...
>> py> abob = bob(doit=doit)
>> py>
>> py> abob.doit()
>> wuzzup?
>>
>> Much to my surprise, this works fine.
>
>why is that surprising? "doit" is a callable, you wrap it in another
>callable, and then you store it in an attribute.
>
>that's no different from storing a integer as an attribute, and it
>sure doesn't turn your callable into an instance method.
>
>> 1. What exactly is going on?
>
>see above.
>
>> 2. How can I get ref to self passed to doit() if I want it to?
>
>try using this bob instead:
>
> import new
>
> class bob(object):
> def __init__(self, **kwargs):
> for fname, func in kwargs.items():
> setattr(self, fname, new.instancemethod(func, self, bob))
>
ISTM "instancemethod" doesn't really tell the story of what that usage means, which is actually
storing a bound method as an attribute of the instance it _happens_ to be bound to.
I.e., this "instancemethod" is a bound method that could be stored as an attribute of _anything_
and if used as a callable the function would see the same bound "self" no matter where the bound
method was picked up from (well, unless someone perversely interfered with some hack ;-)
I am wondering whether anyone mistakenly thinks that there is a dynamic binding process
involved at the time of the attribute access for the instancemethod, as there is for
an ordinary method. Of course I know you know how to mess with the class to make function
attributes of instances get dynamically bound as if they were class attributes accessed
via the instance, but I wonder if others appreciate this distinction, or would be surprised by e.g.,
>>> import new
>>>
>>> class bob(object):
... def __init__(self, **kwargs):
... for fname, func in kwargs.items():
... setattr(self, fname, new.instancemethod(func, self, bob))
...
>>> def m(self, *args):
... return self, args
...
>>> b = bob(bm=m)
>>> vars(b)
{'bm': <bound method bob.m of <__main__.bob object at 0x02EF16EC>>}
>>> b.bm('hi')
(<__main__.bob object at 0x02EF16EC>, ('hi',))
>>> bmg = b.bm
>>> bmg('hello')
(<__main__.bob object at 0x02EF16EC>, ('hello',))
>>> class C: pass
...
>>> c=C()
>>> c.m = b.bm
>>> c.m('greets')
(<__main__.bob object at 0x02EF16EC>, ('greets',))
>>> C.M = b.bm
>>> C.M('saludos')
(<__main__.bob object at 0x02EF16EC>, ('saludos',))
>>> c.M('amigos')
(<__main__.bob object at 0x02EF16EC>, ('amigos',))
Obviously "self" has nothing to do with c or C etc.
Regards,
Bengt Richter
More information about the Python-list
mailing list