On Sun, Apr 15, 2012 at 13:48, Nick Coghlan <ncogh...@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...@gmail.com> wrote: >> On Tue, Apr 19, 2011 at 16:10, Nick Coghlan <ncogh...@gmail.com> wrote: >>> Initially I was going to suggest making __build_class__ 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 __build_class__ > 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 __build_class__(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(my_ns) # add the attributes we want >> cls = type(name, bases, ns) >> >> What about an "operator.build_class(name, bases, ns, **kw)" function? >> It would work like this: >> >> def build_class(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 build_class >> cls = build_class(name, bases, ns, **my_kwargs) > > 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 build_class(name, bases=(), kwds=None, eval_body=None): > metaclass, ns = _prepare(name, bases, kwds) > if eval_body is not None: > eval_body(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 _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com