python动态设置非实例类属性

gnr*_*gnr 3 python attributes metaprogramming

我正在尝试动态添加类属性,但不是在实例级别。例如我可以手动执行以下操作:

class Foo(object):
    a = 1
    b = 2
    c = 3
Run Code Online (Sandbox Code Playgroud)

我希望能够做到:

class Foo(object):
    dct = {'a' : 1, 'b' : 2, 'c' : 3}
    for key, val in dct.items():
        <update the Foo namespace here>
Run Code Online (Sandbox Code Playgroud)

我希望能够做到这一点,而无需从类外部调用该类(因此它是可移植的),或者不需要额外的类/装饰器。这可能吗?

kin*_*all 5

从您的示例代码来看,您希望在创建类的同时执行此操作。在这种情况下,假设您使用的是 CPython,则可以使用locals().

class Foo(object):
    locals().update(a=1, b=2, c=3)
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为在定义类时,locals()会引用类名称空间。它是特定于实现的行为,可能不适用于更高版本的 Python 或替代实现。

下面显示了一个使用类工厂的不太脏的版本。基本思想是通过type()构造函数将字典转换为类,然后将其用作新类的基类。为了方便用最少的语法定义属性,我使用了约定**来接受属性。

def dicty(*bases, **attrs):
    if not bases:
        bases = (object,)
    return type("<from dict>", bases, attrs)

class Foo(dicty(a=1, b=2, c=3)):
    pass

# if you already have the dict, use unpacking

dct = dict(a=1, b=2, c=3)

class Foo(dicty(**dct)):
    pass
Run Code Online (Sandbox Code Playgroud)

这实际上只是称呼type()自己的语法糖。这工作得很好,例如:

 class Foo(type("<none>", (object,), dict(a=1, b=2, c=3))):
     pass
Run Code Online (Sandbox Code Playgroud)