[Python-Dev] Providing a mechanism for PEP 3115 compliant dynamic class creation

Nick Coghlan ncoghlan at gmail.com
Sat Apr 21 17:30:34 CEST 2012


On Sun, Apr 22, 2012 at 12:55 AM, PJ Eby <pje at telecommunity.com> wrote:
> (Sorry I'm so late to this discussion.)
>
> I think that it's important to take into account the fact that PEP 3115
> doesn't require namespaces to implement anything more than __setitem__ and
> __getitem__ (with the latter not even needing to do anything but raise
> KeyError).
>
> Among other things, this means that .update() is right out as a
> general-purpose solution to initializing a 3115-compatible class: you have
> to loop and set items explicitly.  So, if we're providing helper functions,
> there should be a helper that handles this common case by taking the
> keywords (or perhaps an ordered sequence of pairs) and doing the looping for
> you.
>
> Of course, once you're doing that, you might as well implement it by passing
> a closure into __build_class__...

Yeah, the "operator.build_class" in the tracker issue ended up looking
a whole lot like the signature of CPython's __build_class__. The main
difference is that the class body evaluation argument moves to the end
and becomes optional in order to bring the first two arguments in line
with those of type(). The signature ends up being effectively:

    def build_class(name, bases=(), kwds={}, exec_body=None):
        ...

Accepting an optional callback that is given the prepared namespace as
an argument just makes a lot more sense than either exposing a
separate prepare function or using the existing __build_class__
signature directly (which was designed with the compiler in mind, not
humans).

> Personally, I think __build_class__ should be explicitly exposed and
> supported, if for no other reason than that it allows one to re-implement
> old-style __metaclass__ support in 2.x modules that rely on it...  and I
> have a lot of those to port.  (Which is why I also think the convenience API
> for PEP 3115-compatible class creation should actually call __build_class__
> itself.  That way, if it's been replaced, then the replaced semantics would
> *also* apply to dynamically-created classes.)

No, we already have one replaceable-per-module PITA like that (i.e.
__import__). I don't want to see us add another one.

> Having other convenience functions that reimplement lower-level features
> than __build_class__ (like the prepare thing) sounds like a good idea, but I
> think we should encourage common cases to just call something that keeps the
> __setitem__ issue out of the way.
>
> Thoughts?

Agreed on the use of a callback to avoid making too many assumptions
about the API provided by the prepared namespace.

Definitely *not* agreed on making __build_class__ part of the language
spec (or even officially supporting people that decide to replace it
with their own alternative in CPython).

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia


More information about the Python-Dev mailing list