Generating methods in a class

Christopher T King squirrel at WPI.EDU
Tue Jul 6 09:35:12 EDT 2004


On Tue, 6 Jul 2004, C GIllespie wrote:

> What is a quick way of generating all these methods? I'm thinking along the
> lines of:
> 
> 
> class file:
>     formats=['ps', 'ps2', 'hpgl', 'pcl', 'mif', 'pic', 'gd', 'gd2', 'gif',
> 'jpg']
>     def __init__(self):
>         for frmt in self.formats:
>             self.__setattr__('file2'+frmt, ???)
> 
> I've tried a variety of things where ??? is, but with no success.

You've probably tried using ??? = lambda: frmt, with the effect that all 
the functions return 'jpg'. This has bit me before, too. The problem with 
this approach is that frmt is not evaluated inside the lambda -- after the 
loop has finished, you end up with a bunch of "lambda: frmt"s, and frmt is 
left equal to "jpg". The way to fix this is to force frmt to be evaluated, 
as follows:

class file:
    formats=['ps', 'ps2', 'hpgl', 'pcl', 'mif', 'pic', 'gd', 'gd2', 'gif',
'jpg']
    def __init__(self):
        for frmt in self.formats:
            setattr(self, 'file2'+frmt, self.genfunc(frmt))

    def genfunc(self,frmt):
        return lambda: frmt

Calling genfunc() forces frmt to be evaluated before being re-bound and 
passed to the lambda.

There are a couple of problems with placing this all in __init__, however: 
the functions are generated each time you create a new file object, and 
they aren't passed a "self" reference. To fix these problems, it's best to 
add all the methods to the class itself, and not the individual objects:

class file:
    formats=['ps', 'ps2', 'hpgl', 'pcl', 'mif', 'pic', 'gd', 'gd2', 'gif',
'jpg']

    def genfunc(frmt):
        return lambda self: frmt
    genfunc=staticmethod(genfunc)

for frmt in file.formats:
    setattr(file, 'file2'+frmt, file.genfunc(frmt))

Note that neither formats nor genfunc() need to be members of file; if it 
suits your taste better, the same thing can be written as:

class file:
    pass

formats=['ps', 'ps2', 'hpgl', 'pcl', 'mif', 'pic', 'gd', 'gd2', 'gif',
'jpg']

def genfunc(frmt):
    return lambda self: frmt

for frmt in formats:
    setattr(file, 'file2'+frmt, genfunc(frmt))

Personally, I prefer the version using static attributes of the class, but 
either way will work as well.




More information about the Python-list mailing list