2

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

2 回答 2

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()hack 真的只是一个丑陋的把戏,应该避免。

于 2013-11-01T16:17:52.870 回答
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 实现细节。

于 2013-11-01T16:21:27.013 回答