动态创建类属性

Posted

技术标签:

【中文标题】动态创建类属性【英文标题】:Dynamically create class attributes 【发布时间】:2011-02-04 17:34:30 【问题描述】:

我需要从 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__ 用于类创建,以便从字典中动态创建这些属性并节省大量代码和愚蠢的工作。

你会怎么做?

非常感谢您!

【问题讨论】:

【参考方案1】:

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

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

【讨论】:

我们如何传递默认值,或者我们如何初始化这个设置类的任何对象 与@vijayshanker 相同的问题 代码取决于定义Settings类时在范围内的defaults字典。 SettingsMetaSettings 在 setting.py 文件中?我如何将默认参数传递给它? 使用当前代码,你不能传递任何东西,defaults 字典取自范围,在Settings 类之前定义。为了能够传递默认值,您需要对其进行重组。但这感觉与最初提出的问题不同。【参考方案2】:

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

【讨论】:

您还需要在装饰器函数的末尾返回“装饰”类(第一个示例中的cls),不是吗?我花了一段时间才弄清楚,但除非我这样做,否则定义后的类将等于 None。我是否遗漏了一些东西,例如通过引用提供类的某种方式? 我如何将默认值传递给这样的文件 a = Settings(defaults) settings.py 是一个特定的文件【参考方案3】:

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

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

【讨论】:

-1 documentation for locals() 表示不应修改返回的字典内容。

以上是关于动态创建类属性的主要内容,如果未能解决你的问题,请参考以下文章

c#创建对象并动态添加属性

[python]动态创建类

如何使用动态对象类创建 .net 核心 MVC 模型?

spring能动态给一个类增加一个方法或属性吗

python类对象动态添加属性和方法

快速动态创建对象并设置属性