21

我需要从 DEFAULTS 字典动态创建类属性。

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

我也可以通过做某事来实现这一点。就像__init__创建类一样,为了从字典中动态创建这些属性并节省大量代码和愚蠢的工作。

你会怎么做?

非常感谢您!

4

3 回答 3

30

你可以在没有元类的情况下使用装饰器来做到这一点。这种方式更清楚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 中的对象本身。

于 2010-04-06T10:16:43.987 回答
4

我认为元类就是这种情况:

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
于 2010-04-06T08:54:47.120 回答
2

定义类时,局部命名空间会在类体结束时转换为类命名空间。因此,您可以通过以下方式完成此操作:

class Settings(object):
    for key, val in defaults.iteritems():
        locals()[key] = some_complex_init_function(val, ...)
于 2010-04-06T11:42:12.780 回答