Automatic transformation from getter/setter to properties
automatic-properties, metaprogramming, properties, python
Solution
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
Problem
I have a big library 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 re-implement 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`, etc... 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 lets me to choose to skip some getter/setter couples where it is better to do the work by hand.