【问题标题】:Dynamic Class Variables - locals() vs __metaclass__动态类变量 - locals() 与 __metaclass__
【发布时间】:2026-02-05 17:30:02
【问题描述】:

要创建动态类变量,您似乎有两个选择 - 使用 locals()__metaclass__。我不喜欢分配给locals(),但它似乎在类定义中起作用,并且比__metaclass__ 替代方案更简洁。

这样使用locals()靠谱吗?这两种解决方案的优缺点是什么?

meta_attrs = ["alpha", "beta", "gamma"]

class C(object):
    local_context = locals()
    for attr in meta_attrs:
        local_context[attr] = attr.upper()


class D(object):
    class __metaclass__(type):
        def __new__(mcs, name, bases, attrs):
            for attr in meta_attrs:
                attrs[attr] = attr.upper()
            return type.__new__(mcs, name, bases, attrs)


if __name__ == '__main__':
    print C.alpha, C.beta, C.gamma
    print D.alpha, D.beta, D.gamma

【问题讨论】:

  • 第三个选项是设置属性的类装饰器或工厂函数。

标签: python metaprogramming metaclass


【解决方案1】:

正如 kindall 所说,类装饰器是第三种选择:

meta_attrs = ["alpha", "beta", "gamma"]

def decorate(klass):
    for attr in meta_attrs:
        setattr(klass, attr, attr.upper())
    return klass

@decorate
class C(object):
    pass

这是第四个选项:

meta_attrs = ["alpha", "beta", "gamma"]

class C(object):
    pass

for attr in meta_attrs:
    setattr(C, attr, attr.upper())

我自己会选择第五个选项:没有动态类属性。我看不到用例。如果我真的需要它,我可能会使用第四个选项,除非我需要在多个课程中使用它,否则我会使用装饰器。

元类通常过于复杂,locals() hack 真的只是一个丑陋的把戏,应该避免。

【讨论】:

    【解决方案2】:

    __metaclass__ 可以是任何可调用的:

    class D(object):
        def __metaclass__(name, bases, dct):
            for attr in meta_attrs:  
                dct[attr] = attr.upper()
            return type(name, bases, dct)
    

    这几乎与locals() 方法一样简洁,并且不依赖于CPython 实现细节。

    【讨论】:

    • 我接受了这个,因为它保留了课堂上的逻辑,这就是我想要的。另外,我学到了一些新东西。谢谢!