Frage

To create dynamic class variables you seem to have two options - using locals() or __metaclass__. I am not a fan of assigning to locals() but it seems to work in a class definition and is more succinct than it's __metaclass__ alternative.

Is it reliable to use locals() in this way? What are the advantages/drawbacks for either solution?

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
War es hilfreich?

Lösung 2

__metaclass__ can be any callable:

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

This is almost as concise as the locals() method, and doesn't rely on CPython implementation details.

Andere Tipps

As mentioned by kindall, a class decorator is a third option:

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

Here's a fourth option:

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

class C(object):
    pass

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

I would go for a fifth option myself: Not having dynamic class attributes. I can't see the use case. If I really needed it, I'd probably use the fourth option, unless I needed it on more than one class, then I would use a decorator.

Metaclasses are often overly complicated, and the locals() hack really is just an ugly trick and should be avoided.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top