Dynamically create class attributes
Solution 1
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.
Solution 2
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
Solution 3
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, ...)
xyz-123
Updated on June 06, 2022Comments
-
xyz-123 about 2 years
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!
-
martineau over 13 years-1 The documentation for
locals()
says the contents of the dictionary returned should not be modified. -
Simon over 11 yearsYou also need to return the "decorated" class (
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 equalNone
after definition. Am I missing something, like for example some way of supplying the class by reference instead? -
vijay shanker over 8 yearshow do we pass defaults, or how can we initialize any object of this Settings Class
-
TomSawyer over 6 yearsHow do i pass defaults to the file like this
a = Settings(defaults)
settings.py
is a particular file -
TomSawyer over 6 yearssame question with @vijayshanker
-
Łukasz over 6 yearsThe code depends on the
defaults
dictionary being in scope when definingSettings
class. -
TomSawyer over 6 years
SettingsMeta
andSettings
in the setting.py file? How do i pass defaults parameter to it? -
Łukasz over 6 yearsWith the current code, you cannot pass anything, the
defaults
dictionary is taken from the scope, defined beforeSettings
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.