python 动态创建类属性

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2583620/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-04 00:59:54  来源:igfitidea点击:

Dynamically create class attributes

pythonclass-attributes

提问by xyz-123

I need to dynamically create class attributes from a DEFAULTS dictionary.

我需要从 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], ...)

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.

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

How would you do this?

你会怎么做?

Thank you very much in advance!

非常感谢您提前!

回答by nkrkv

You could do it without metaclasses using decorators. This way is a bit more clear IMO:

您可以使用装饰器在没有元类的情况下做到这一点。这种方式更清晰一点 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:

在 Python 2.6 之前,类装饰器不可用。所以你可以写:

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

in older versions of python.

在旧版本的python中。

In the provided example apply_defaultsis 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:

在提供的示例中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, ...))

This is possible since classes (in the sense of types) are objects themselves in Python.

这是可能的,因为类(在类型的意义上)是 Python 中的对象本身。

回答by ?ukasz

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

回答by Brian

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