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

PJ Eby pje at telecommunity.com
Sat Apr 21 19:21:14 CEST 2012


On Sat, Apr 21, 2012 at 11:30 AM, Nick Coghlan <ncoghlan at gmail.com> wrote:

> On Sun, Apr 22, 2012 at 12:55 AM, PJ Eby <pje at telecommunity.com> wrote:
> > 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.
>

Well, it's more like replacing than adding; __metaclass__ has this job in
2.x.  PEP 3115 removed what is (IMO) an important feature: the ability for
method-level decorators to affect the class, without needing user-specified
metaclasses or class decorators.

This is important for e.g. registering methods that are generic functions,
without requiring the addition of redundant metaclass or class-decorator
statements, and it's something that's possible in 2.x using __metaclass__,
but *not* possible under PEP 3115 without hooking __build_class__.
 Replacing builtins.__build_class__ allows the restoration of __metaclass__
support at the class level, which in turn allows porting 2.x code that uses
this facility.

To try to be more concrete, here's an example of sorts:

class Foo:
    @decorate(blah, fah)
    def widget(self, spam):
         ...

If @decorate needs access to the 'Foo' class object, this is not possible
under PEP 3115 without adding an explicit metaclass or class decorator to
support it.  And if you are using such method-level decorators from more
than one source, you will have to combine their class decorators or
metaclasses in some way to get this to work.  Further, if somebody forgets
to add the extra metaclass(es) and/or class decorator(s), things will
quietly break.

However, under 2.x, a straightforward solution is possible (well, to me
it's straightforward) : method decorators can replace the class'
__metaclass__ and chain to the previous one, if it existed.  It's like
giving method decorators a chance to *also* be a class decorator.

Without some *other* way to do this in 3.x, I don't have much of a choice
besides replacing __build_class__ to accomplish this use case.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20120421/9ce44fdc/attachment.html>


More information about the Python-Dev mailing list