I need to dynamically create class attributes from a DEFAULTS dictionary.
defaults = {
'default_value1':True,
'default_value2':True,
'default_value3':True,
}
class Settings(object):
default_value1 = some_complex_init_function(defaults[default_value1], ...)
default_value2 = some_complex_init_function(defaults[default_value2], ...)
default_value3 = some_complex_init_function(defaults[default_value3], ...)
I could also achive this by having sth. like __init__ for class creation, in order to dynamically create these attributes from dictionary and save a lot of code and stupid work.
How would you do this?
Thank you very much in advance!
3 Answers 3
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_defaults
class Settings(object):
pass
Prior to Python 2.6 class decorators were unavailable. So you can write:
class Settings(object):
pass
Settings = 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.
2 Comments
cls in the first example) at the end of the decorator function, don't you? Took me a while to figure out, but unless I do this the class will equal None after definition. Am I missing something, like for example some way of supplying the class by reference instead?a = Settings(defaults) settings.py is a particular fileI 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
5 Comments
defaults dictionary being in scope when defining Settings class.SettingsMeta and Settings in the setting.py file? How do i pass defaults parameter to it?defaults dictionary is taken from the scope, defined before Settings class. To be able to pass the defaults, you would need to restructure it. But it feels like a different question to the one asked originally.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, ...)
1 Comment
locals() says the contents of the dictionary returned should not be modified.