[reportlab-users] Question about passing function to labelTextFormat

Robin Becker reportlab-users@reportlab.com
Tue, 16 Sep 2003 23:18:46 +0100


In article <64972.199.169.240.132.1063745970.squirrel@svr1.turboweb.net>
, reportlab@sarcastic-horse.com writes
>Hi-
>
>I have been making lineplots of time series data by converting the dates
>to integers, where 1 is the beginning of the date range I want to graph.
>
>For example, if I want to plot a series from November, 1999 to March,
>2000, then I convert:
>
>November, 1999 => 1
>December, 1999 => 2
>January, 2000 => 3
>Februrary, 2000 => 4
>March, 2000 => 5
>
>You get the idea.
>
>Then, to print x-axes with the dates, I wrote this function:
>
>def mk_date_labels(i):
>    dates = ['November, 1999', 'December, 1999', ... ] #you get the idea
>    return dates[i]
>
>Then I have been passing this function to
>reportlab.graphics.charts.axes.XValueAxis.labelTextFormat like so:
>
>lp.xValueAxis.labelTextFormat = num2str #lp is my LinePlot() object
>
>This is great, but I want to change the mk_date_labels to get 2 args: the
>indexing number, and also, the list to use to get the text string.  How do
>I write the function that way?  I don't know enough about passing
>functions as parameters to figure it out.
....
in python you can have a keyword argument set at definition time.
So you can have a factory function like

def get_labels_func(dates):
    def num2str(i,dates=dates):
        return dates[i]
    return num2str

ie get_labels_func is a function that returns a function. we know that
the result function will be called with one argument, i, so dates will
be kept with its default value which we pass in at creation time.

So now you should be able to do

lp.xValueAxis.labelTextFormat = get_labels_func(['November, 1999',
'December, 1999', ... ,'December 2003'])

ie the strings become deciable at run time.


Another way to do this is to set lp.xValueAxis.labelTextFormat to a
callable instance since we test only for callability (not that it's a
function).

This way is probably more pythonic.

class MyLabeller:
    def __init__(self,info):
        self.info = info

    def __call__(self,i):
        return self.info[i]

not that although I have written the example above with self.info as a
simple list it could be anything that helps to get the required string
when i is given in the special __call__ method.

Going on with this scheme we just set

lp.xValueAxis.labelTextFormat = MyLabeller(['November, 1999',
'December, 1999', ... ,'December 2003'])

MyLabeller([...]) produces an instance which is callable ie we

can do 
>>> lf = MyLabeller(['A','B','C'])
>>> lf(1)
'B'
>>> 
hope this helps.
-- 
Robin Becker