[Tutor] dynamic class method creation?

maddox flower maddoxflower at web.de
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: 
http://groups.google.com/groups?q=g:thl1797684596d&dq=&hl=en&lr=lang_en&ie=UTF-8&oe=UTF-8&safe=active&selm=mailman.997701621.7351.python-list%40python.org&rnum=69
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?

Cheers,   maddox














More information about the Tutor mailing list