动态类变量 - locals()vs __metaclass__

时间:2013-11-01 16:10:42

标签: python metaprogramming metaclass

要创建动态类变量,您似乎有两个选项 - 使用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

2 个答案:

答案 0 :(得分:4)

正如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()黑客真的只是一个丑陋的伎俩,应该避免。

答案 1 :(得分:1)

__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实现细节。