Am 11.04.2013 10:19, schrieb Steven D'Aprano:
if sys.version >= '3':

Use sys.version_info >= (3,), otherwise your code breaks when upgrading to Python 10 and greater. ;^)


The second question that came up was if there is a way to keep a
metaclass defined inside the class or if the only way is to provide it
externally. [...]

Not in general, since the metaclass has to exist independently of the
class.

Thanks for your explanations, they are appreciated.


> The class is an instance of your metaclass. That means that the
> metaclass must exist first, so it can be instantiated when you
> define the class.

I don't like the approach to define the code to post-process a class before defining the class. It's a bit like top-posting, it messes up the reading order. Since I really intend to post-process the class, it seems that metaclasses are simply not the right tool.

At the moment, this leaves me with two options:

1. post-process the class

class X:
    pass
# attach constants to clas X
for i in (1, 2, 3):
    setattr(X, 'f{}' % i, i)

2. generate code inline

class Y: pass
    # generate constants in local (class-)namespace
    for i in (1, 2, 3):
        locals()['f{}' % i] = i

In both cases, variables (loop variable 'i') are leaked into the surrounding namespace, which is kind-of ugly. The second approach also seems a bit hackish and I can't use the class-in-definition there, which is limiting when you want to attach e.g. constants of type X to X.


Also PEP 3115 "Metaclasses in Python 3000"[2] seems to
consider postprocessing of a class definition as better handled by a
class decorator, which is something I haven't looked at yet.

Generally, class decorators are less brain-melting than metaclasses.

Alas, they also need to be defined before the class, messing with the mentioned order of declaration. They can be used to call a class function though which then does the necessary postprocessing...

3. post-process the class triggered with decorator

def postprocess_class(cls):
    """invoke postprocess() on the decorated object"""
    cls.postprocess()
    del cls.postprocess
    return cls

@postprocess_class
class Z:
    @classfunction
    def postprocess(cls):
        # attach constants to class
        for i in (1, 2, 3):
            setattr(cls, 'f{}' % i, i)


I guess I'll stay with variant 1 for now, since it requires the least amount of code and the least amount of questions from other developers here.

Thanks everybody!

Uli



--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to