bound vs unbound functions

M

Michael Tobis

I'm trying to do metaprogramming. I'm sure I've got this all wrong
wrong wrong, but somehow my approach hasn't yet hit a brick wall.

Anyway, I'd like to dynamically add a method to an instance at
instantiation time. Something like

######
In [71]: class quux(object):
.....: def __init__(self,stuff):
.....: template = "def foo(self,b): print b + %s" % stuff
.....: exec(template)
.....: self.bazz = foo
.....:


In [72]: q = quux(5)

In [73]: q.bazz(4)
---------------------------------------------------------------------------
TypeError Traceback (most recent call
last)

/Users/tobis/PyNSol/<console>

TypeError: foo() takes exactly 2 arguments (1 given)

In [74]: q.bazz("not much",4)
9
########

So the straightforward question is why, even though bazz is a method of
class quux, it doesn't have that extra call parameter 'self'. Is this a
problem? If I actually need a reference to self is it OK to do:

In [76]: q.bazz(q,4)

?

The more vague question is why do people despise 'exec', and how should
I do this sort of thing instead?

mt

PS - any idea how to get past google's stupid formatting these days? I
thought they were supposed to like python, but they just ignore leading
blanks.
 
T

Terry Reedy

I'd like to dynamically add a method to an instance at
instantiation time.

No can do. A method is function that is an attribute of a class, even if
accessed via an instance. A function added to an instance as an attribute
of the instance remains a function. It is instance-specific data that
methods and other code can use, just like other instance data, for
instance-specific effects. Two common examples:

class composer:
# skip obvious init
def __call__(self, x): return self.outer(self.inner(x))

sincos = composer(math.sin, math.cos)
# yes, this can also be done with composer function with nested scope

class memoizer: # posted several times
# skip init again
def __call__(self,x):
# return previously computed self.memodict[x] if it exists
# or calculate, store, and return self.func(x)

\> PS - any idea how to get past google's stupid formatting these days? I
thought they were supposed to like python, but they just ignore leading
blanks.

Don't use google to post on clp. Go to news.gmane.org instead.

Terry J. Reedy
 
K

Kent Johnson

Michael said:
I'm trying to do metaprogramming. I'm sure I've got this all wrong
wrong wrong, but somehow my approach hasn't yet hit a brick wall.

Anyway, I'd like to dynamically add a method to an instance at
instantiation time. Something like

######
In [71]: class quux(object):
....: def __init__(self,stuff):
....: template = "def foo(self,b): print b + %s" % stuff
....: exec(template)
....: self.bazz = foo
....:


In [72]: q = quux(5)

In [73]: q.bazz(4)
---------------------------------------------------------------------------
TypeError Traceback (most recent call
last)

/Users/tobis/PyNSol/<console>

TypeError: foo() takes exactly 2 arguments (1 given)

In [74]: q.bazz("not much",4)
9
########

The thread Steve quoted suggests using new.instancemethod():

import new

class quux(object):
def __init__(self,stuff):
template = "def foo(self,b): print b + %s" % stuff
exec(template)
self.bazz = new.instancemethod(foo, self, quux)


There is no need for exec; you can define foo() directly as a nested function:

class quux(object):
def __init__(self,stuff):
def foo(self,b):
print b + stuff
self.bazz = new.instancemethod(foo, self, quux)


Of course for this simple example you can just remember stuff as an attribute:

class quux(object):
def __init__(self,stuff):
self.stuff = stuff

def bazz(self, b):
print b + self.stuff

Kent
So the straightforward question is why, even though bazz is a method of
class quux, it doesn't have that extra call parameter 'self'. Is this a
problem? If I actually need a reference to self is it OK to do:

In [76]: q.bazz(q,4)

?

The more vague question is why do people despise 'exec', and how should
I do this sort of thing instead?
 
T

Terry Reedy

Feel free to ignore this. Some system falsely labeled this post (sent via
gmane) as possible spam. I am sending it back in the opposite direction to
see what transpires that way. Sorry for the disturbance. tjr

Terry Reedy said:
I'd like to dynamically add a method to an instance at
instantiation time.

No can do. A method is function that is an attribute of a class, even if
accessed via an instance. A function added to an instance as an
attribute of the instance remains a function. It is instance-specific
data that methods and other code can use, just like other instance data,
for instance-specific effects. Two common examples:

class composer:
# skip obvious init
def __call__(self, x): return self.outer(self.inner(x))

sincos = composer(math.sin, math.cos)
# yes, this can also be done with composer function with nested scope

class memoizer: # posted several times
# skip init again
def __call__(self,x):
# return previously computed self.memodict[x] if it exists
# or calculate, store, and return self.func(x)

\> PS - any idea how to get past google's stupid formatting these days? I
thought they were supposed to like python, but they just ignore leading
blanks.

Don't use google to post on clp. Go to news.gmane.org instead.

Terry J. Reedy
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top