Metaclasses / Decorators for magick with functions

Ian Sparks Ian.Sparks at etrials.com
Mon Nov 22 14:49:54 EST 2004


Hi all,

I wanted to do some magick to classes so that any method.__name__.startswith('list') would be expected to return a list and would magically wrap the elements of that list with an ItemWrapper() instance.

For instance, this might be useful for automatically wrapping the rows of a cursor result set from a database with the excellent dtuple. Besides, it's evil, and sometimes evil is good. ;)

This is what I came up with using Python 2.3 (no @ available). Is there a better way?  

class ItemWrapper:
    """A class that wraps an item in a list"""
    def __init__(self,item):
        self.item = item

    def val(self): 
        """Example wrapped method"""
        return self.item
        
class ListWrapper:
    """
    Wraps the elements of a functions return list with
    ItemWrapper() instances
    """
    def __init__(self,f):
        self.f = f
            
    def __call__(self,*args,**kwds):
        vals = self.f(self.f,*args,**kwds)
        return [ItemWrapper(x) for x in vals]

class MyMeta(type):
    """
    Metaclass that will wrap methods who's names
    start with 'list' with ListWrappers
    """
    def __new__(cls, name, bases, dct):
        for key,item in dct.items():
            if key.startswith('list'):
                import types
                if type(item) == types.FunctionType:
                    dct[key] = ListWrapper(dct[key])
        return type.__new__(cls, name, bases, dct)

class ParentTest:
    """
    Parent class to inherit from, so folks know that they're
    declaring a class with magick
    """
    __metaclass__ = MyMeta
    
class Test(ParentTest):
    """
    A class who's listXXX methods return lists of ItemWrappers()
    instead of what is expected. BWWWWAHAHAHAHAH!
    """
    def list1(self):
        return [1,2,3,4]

if __name__ == '__main__':

    t = Test()
    vals = t.list1()
    for x in vals:
        print x,x.val()



More information about the Python-list mailing list