Dynamically adding a runtime generated method to a class.

J

Joe Goldthwaite

I'm not sure how to even ask this question. I'm working on a financial
reporting application. The current system is very limited in what it can
display. You can see reports with columns of Period, Quarter, Year to date
or you can see a yearly trend. I'd like for the users to be able to define
the columns on the fly but I'm not sure how to do it in Python in the
cleanest most efficient manner.

The easy way would be to keep a list of class methods like this;
#My first attempt
class lineClass1:

def __init__(self, desc, trend):

self.desc = desc
self.trend = trend

def Ptd(self, per):
return self.trend[per]

def Ytd(self, per):
return sum(self.trend[:per])

def getLine(self, cols, per):

# return the descriptionin the first column
vals = [self.desc]
for col in cols:
vals.append(col(self, per))
return vals

# create the instance
line1 = lineClass1('Some Description', [1,2,3,4,5,6,7,8,9,10,11,12])

# Now I can get the columns out in the order I want by passing in a list
of methods
cols = [lineClass1.Ptd, lineClass1.Ytd]
print line1.getLine(cols, 5)

This would work and not be too terribly inefficient but I was thinking it
would be much better generate the getLine method at runtime and dynamically
add it to the class so I wouldn't have to pass the columns around and loop
through them every time;

#Define the class with just the trend
class lineClass2:

def __init__(self, desc, trend):

self.desc = desc
self.trend = trend

def Ptd(self, per):

return self.trend[per]

def Ytd(self, per):

return sum(self.trend[:per])

#
****************************************************************************
************
# Here, I want to dyamically add a class method that has the return
line below defined at runtime
#
def getLine(self, per):
return [self.desc, self.Ptd(per), self.Ytd(per)]

# create a couple of instances
line = lineClass('Some Description', [1,2,3,4,5,6,7,8,9,10,11,12])

# try it out.
print line.getLine(5)

Is there any way to dynamically generate the getLine function at runtime?
Can the eval statement do that?
 
M

Martin v. Löwis

This would work and not be too terribly inefficient but I was thinking
it would be much better generate the getLine method at runtime and
dynamically add it to the class so I wouldn't have to pass the columns
around and loop through them every time;

I would advise against that. Generating methods on the fly is fairly
involved (although possible); but I see no gain.

If you don't want to pass the cols around (which I can see as
desirable), I recommend to make them an instance variable:

def getLine(self, per):

vals = [self.desc]
for col in self.cols:
vals.append(col(self, per))
return vals

line1 = lineClass1('Some Description', [1,2,3,4,5,6,7,8,9,10,11,12])
line1.cols = [lineClass1.Ptd, lineClass1.Ytd]

print line1.getLine(5)

HTH,
Martin
 
M

Martin v. Löwis

This would work and not be too terribly inefficient but I was thinking
it would be much better generate the getLine method at runtime and
dynamically add it to the class so I wouldn't have to pass the columns
around and loop through them every time;

I would advise against that. Generating methods on the fly is fairly
involved (although possible); but I see no gain.

If you don't want to pass the cols around (which I can see as
desirable), I recommend to make them an instance variable:

def getLine(self, per):

vals = [self.desc]
for col in self.cols:
vals.append(col(self, per))
return vals

line1 = lineClass1('Some Description', [1,2,3,4,5,6,7,8,9,10,11,12])
line1.cols = [lineClass1.Ptd, lineClass1.Ytd]

print line1.getLine(5)

HTH,
Martin
 

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

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top