Динамично создайте атрибуты класса

Я должен динамично создать атрибуты класса из словаря ЗНАЧЕНИЙ ПО УМОЛЧАНИЮ.

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], ...)

Я мог также achive это при наличии sth. как __init__ для создания класса, чтобы динамично создать эти атрибуты из словаря и сохранить много кода и глупой работы.

Как Вы сделали бы это?

Заранее большое спасибо!

15
задан SilentGhost 6 April 2010 в 10:30
поделиться

3 ответа

При определении класса локальное пространство имен будет преобразовано в пространство имен класса в конце тела класса. Таким образом, вы можете сделать это с помощью:

class Settings(object):
    for key, val in defaults.iteritems():
        locals()[key] = some_complex_init_function(val, ...)
2
ответ дан 1 December 2019 в 02:19
поделиться

Вы можете сделать это без метаклассов, используя декораторы. Этот способ немного более понятен 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

До Python 2.6 декораторы классов были недоступны. Поэтому вы можете написать:

class Settings(object):
    pass
Settings = apply_defaults(Settings)

в старых версиях python.

В приведенном примере apply_defaults является многоразовым... Ну, за исключением того, что значения по умолчанию жестко закодированы в теле декоратора :) Если у вас всего один случай, вы можете упростить код до следующего:

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, ...))

Это возможно, поскольку в Python классы (в смысле типы) сами являются объектами.

24
ответ дан 1 December 2019 в 02:19
поделиться

Я думаю, что это случай для метакласса:

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
3
ответ дан 1 December 2019 в 02:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: