Самым близким, что я видел в Python для генерации кода, является функция Python __metaclass__
.Например, вот простой метакласс для создания свойств только для чтения:
class ReadonlyProperties(type):
def __init__(cls, name, bases, attrs):
props = attrs.get("props",[])
if props:
# generate property for each name in propnames
def defineProperty(p):
return property(lambda self: getattr(self, '_'+p))
for p,_ in props:
setattr(cls, p, defineProperty(p))
# generate wrapper for __init__ to initialize property values
if "__init__" in attrs:
setattr(cls, "__orig_init__", attrs["__init__"])
else:
setattr(cls, "__orig_init__", None)
def new__init__fn(self, *args, **kwargs):
if self.__orig_init__:
self.__orig_init__(*args)
for p,pdefault in props:
if p in kwargs:
setattr(self, '_'+p, kwargs[p])
else:
setattr(self, '_'+p, pdefault)
setattr(cls, "__init__", new__init__fn)
# generate __str__ function
def __repr__fn(self):
return "%s(%s)" % (name, ','.join("%s=%s" % (p,getattr(self,p)) for p,_ in props))
setattr(cls, "__repr__", __repr__fn)
# don't need this class property any more
delattr(cls, "props")
Теперь вот метакласс в действии:
class Coord3D(object):
__metaclass__ = ReadonlyProperties
props = [('x',0), ('y',0), ('z',0)]
pt = Coord3D(x=100, y=200)
print repr(pt)
print pt.x
print [n for n in dir(pt) if not n.startswith('__')]
Отпечатки:
Coord3D(x=100,y=200,z=0)
100
['_x', '_y', '_z', 'x', 'y', 'z']
Присвоение pt.x
вызовет AttributeError, поскольку это свойство только для чтения.