[Tutor] dynamic class method creation?

Wed Nov 12 13:57:19 EST 2003

```Thanks for the link. But I still do have a problem: What I want to do is
not only attach a method dynamically to a class, but to create/write it
dynamically. What I tried so far is this:

#########################
from Numeric import *

def sum_string(r, a):
"""returns a string representing an expression;
r is the rank of an array, a is the name of the array.

E.g. sum_string(3, 'ary') returns 'sum(sum(sum(ary)))'
"""

s = "sum(%s)" % a
for i in range(r-1):
s = "sum(%s)" % s
return s

def sumFunc_string(r):
"""returns a string representing the definition of a
function called 'sumFunc';
'sumFunc' is supposed to take an array as an argument and to return
the sum over all elements of the array
"""

s = """
def sumFunc(a):
return %s
""" % sum_string(r, 'a')
return s

my_a = array([[1, 2], [3, 4]])

s = sumFunc_string(rank(my_a))

exec s

print sumFunc(my_a)
#########################

Output:
10

Ok, not bad. So, after creating/writing the function 'sumFunc'
'dynamically' I can actually use it as I would use any other function.
Now, I want to be able to do the following: Create/write a method
dynamically and attach it to an existing class (all inside the __init__
method of the class), so I can use it like a normal method of that
class. Something along the following line (reusing the sum_string
function from the example above):

#########################
def sumFunc_string(r):
"""returns a string representing the definition of a
function called 'sumFunc';
'sumFunc' is supposed to take an array as an argument and to return
the sum over all elements of the array
"""
s = """
def sumFunc(self, a):
return %s
""" % sum_string(r, 'self.a')
return s

class ArrayContainer:
def __init(self, a):
self.a = a
s = sumFunc_string(rank(a))
exec s
self.sum = sumFunc

my_a = array([[1, 2], [3, 4]])

ac = ArrayContainer(my_a)
ac.sum()
#########################

Well, this doesn't work.

After I had had a look at this post by Guido van Rossum:
I came up with this (reuse the sum_string function again):

#########################
class ArrayContainer(object):
__dynamic__ = 1
def __init__(self, a):
self.a = a
##         s = sumFunc_string(rank(a))
##         exec s
##         self.sum = sumFunc

def sumall(self):
return sum(sum(self.a))

def __str__(self):
s = ""
for k in self.__class__.__dict__:
s += "%s: \n" % k
return s

my_a = array([[1, 2], [3, 4]])

s = sumFunc_string(rank(my_a))
exec s
ArrayContainer.sum = sumFunc

ac = ArrayContainer(my_a)

print "function:", sumFunc(ac, ac.a)
print "method:", ac.sum()
#########################

Output:

function: 10
method:
Traceback (most recent call last):
File "<stdin>", line 71, in ?
NameError: name 'insac' is not defined

Why does the 'function' call work, but the 'method' call not? How can I
actually do the exec stuff inside the __init__ method of the
ArrayContainer class?

```