Dynamically create class attributes
You could do it without metaclasses using decorators. This way is a bit more clear IMO:
def apply_defaults(cls): defaults = { 'default_value1':True, 'default_value2':True, 'default_value3':True, } for name, value in defaults.items(): setattr(cls, name, some_complex_init_function(value, ...)) return cls@apply_defaultsclass Settings(object): pass
Prior to Python 2.6 class decorators were unavailable. So you can write:
class Settings(object): passSettings = apply_defaults(Settings)
in older versions of python.
In the provided example apply_defaults
is reusable… Well, except that the defaults are hard-coded in the decorator's body :) If you have just a single case you can even simplify your code to this:
defaults = { 'default_value1':True, 'default_value2':True, 'default_value3':True,}class Settings(object): """Your implementation goes here as usual"""for name, value in defaults.items(): setattr(Settings, name, some_complex_init_function(value, ...))
This is possible since classes (in the sense of types) are objects themselves in Python.
I think that's case for metaclass:
class SettingsMeta(type): def __new__(cls, name, bases, dct): for name, value in defaults.items(): dct[name] = some_complex_init_function(value, ...) return type.__new__(cls, name, bases, dct)class Settings(object): __metaclass__ = SettingsMeta
When defining a class, the local namespace will be converted into the class namespace at the conclusion of the class body. As such, you can accomplish this with:
class Settings(object): for key, val in defaults.iteritems(): locals()[key] = some_complex_init_function(val, ...)