动态创建类属性

21 投票
3 回答
23529 浏览
提问于 2025-04-15 21:17

我需要根据一个默认的字典动态创建类的属性。

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__ 的方法来创建类,这样就能从字典中动态生成这些属性,这样可以省去很多代码和无聊的工作。

你会怎么做呢?

非常感谢你的帮助!

3 个回答

2

在定义一个类的时候,类里面的局部命名空间会在类的主体结束时变成类的命名空间。简单来说,就是你在类里定义的东西,最后会被整理成这个类的一部分。你可以用下面的方式来实现:

class Settings(object):
    for key, val in defaults.iteritems():
        locals()[key] = some_complex_init_function(val, ...)
5

我觉得这就是元类的情况:

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
32

你可以不使用 metaclasses,而是用装饰器来实现。这种方法在我看来更清晰一些:

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 中,类(作为类型的意思)本身就是对象。

撰写回答