Automatic transformation from getter/setter to properties
Question: I have a big libray written in C++ and someone created an interface to use it
in python (2.6) in an automatic way. Now I have a lot of classes with getter
and setter methods. Really: I hate them.

I want to reimplement the classes with a more pythonic interface using
properties. The problem is that every class has hundreds of getters and
setters and I have a lot of classes. How can I automatically create
properties? For example, if I have a class called MyClass with a GetX() and
SetX(x), GetY, SetY, ... methods how can I automatically create a derived
class MyPythonicClass with the property X (readable if there is the getter and
writable if there is the setter), and so on? I would like a mechanism that let
me to choose to skip some getter/setter couples where is better to do the work
by hand.


Answer: Here's a way to do it with a class decorator

    
    
    def make_properties(c):
        from collections import defaultdict
        props=defaultdict(dict)
        for k,v in vars(c).items():
            if k.startswith("Get"):
                props[k[3:]]['getter']=v
            if k.startswith("Set"):
                props[k[3:]]['setter']=v
        for k,v in props.items():
            setattr(c,k,property(v.get('getter'),v.get('setter')))
        return c
    
    @make_properties
    class C(object):
        def GetX(self):
            print "GetX"
            return self._x
    
        def SetX(self, value):
            print "SetX"
            self._x = value
    
    c=C()
    c.X=5
    c.X
    

Here is a slightly more complicated version that allows you to specify a list
of items to skip

    
    
    def make_properties(skip=None):
        if skip is None:
            skip=[]
        def f(c):
            from collections import defaultdict
            props=defaultdict(dict)
            for k,v in vars(c).items():
                if k.startswith("Get"):
                    props[k[3:]]['getter']=v
                if k.startswith("Set"):
                    props[k[3:]]['setter']=v
            for k,v in props.items():
                if k in skip:
                    continue
                setattr(c,k,property(v.get('getter'),v.get('setter')))
            return c
        return f
    
    @make_properties(skip=['Y'])
    class C(object):
        def GetX(self):
            print "GetX"
            return self._x
    
        def SetX(self, value):
            print "SetX"
            self._x = value
    
        def GetY(self):
            print "GetY"
            return self._y
    
        def SetY(self, value):
            print "SetY"
            self._y = value
    
    c=C()
    c.X=5
    c.X
    c.Y=5
    c.Y
    

