[Python-Dev] Providing a mechanism for PEP 3115 compliant dynamic class creation (original) (raw)

Daniel Urban urban.dani+py at gmail.com
Sun Apr 15 21:34:12 CEST 2012


On Sun, Apr 15, 2012 at 13:48, Nick Coghlan <ncoghlan at gmail.com> wrote:

/me pages thoughts from 12 months ago back into brain...

Sorry about that, I planned to do this earlier...

On Sun, Apr 15, 2012 at 7:36 PM, Daniel Urban <urban.dani+py at gmail.com> wrote:

On Tue, Apr 19, 2011 at 16:10, Nick Coghlan <ncoghlan at gmail.com> wrote:

Initially I was going to suggest making buildclass part of the language definition rather than a CPython implementation detail, but then I realised that various CPython specific elements in its signature made that a bad idea.

Are you referring to the first 'func' argument? (Which is basically the body of the "class" statement, if I'm not mistaken). Yup, I believe that was my main objection to exposing buildclass directly. There's no obligation for implementations to build a throwaway function to evaluate a class body. prepare also needs the name and optional keyword arguments.  So it probably should be something like "operator.prepare(name, bases, metaclass, **kw)". But this way it would need almost the same arguments as buildclass(func, name, *bases, metaclass=None, **kwds). True. The correct idiom for dynamic type creation in a PEP 3115 world would then be:

 from operator import prepare  cls = type(name, bases, prepare(type, bases)) Thoughts? When creating a dynamic type, we may want to do it with a non-empty namespace. Maybe like this (with the extra arguments mentioned above): from operator import prepare ns = prepare(name, bases, type, **kwargs) ns.update(myns)  # add the attributes we want cls = type(name, bases, ns) What about an "operator.buildclass(name, bases, ns, **kw)" function? It would work like this: def buildclass(name, bases, ns, **kw): metaclass = kw.pop('metaclass', type) pns = prepare(name, bases, metaclass, **kw) pns.update(ns) return metaclass(name, bases, pns) (Where 'prepare' is the same as above). This way we wouldn't even need to make 'prepare' public, and the new way to create a dynamic type would be: from operator import buildclass cls = buildclass(name, bases, ns, **mykwargs) No, I think we would want to expose the created namespace directly - that way people can use update(), direct assigment, exec(), eval(), or whatever other mechanism they choose to handle the task of populating the namespace. However, a potentially cleaner way to do that might be offer use an optional callback API rather than exposing a separate public prepare() function. Something like:  def buildclass(name, bases=(), kwds=None, evalbody=None):  metaclass, ns = prepare(name, bases, kwds)  if evalbody is not None:  evalbody(ns)  return metaclass(name, bases, ns)

That seems more flexible indeed. I will try to make a patch next week, if that's OK.

Daniel



More information about the Python-Dev mailing list