[Python-Dev] Adding types.build_class for 3.3 (original) (raw)

Daniel Urban urban.dani+py at gmail.com
Wed May 9 08:37:57 CEST 2012


On Wed, May 9, 2012 at 3:10 AM, Nick Coghlan <ncoghlan at gmail.com> wrote:

On Wed, May 9, 2012 at 8:37 AM, Tres Seaver <tseaver at palladion.com> wrote:

No, the "mcl" in the call is just the designated metaclass - the actual metaclass of the resulting class definition may be something different. That's why this is a separate method from mcl.new.

Why not make it a static method, if there is no notion of a useful 'cls' argument? We need the explicitly declared metaclass as well as the bases in order to determine the correct metaclass.

Note, that the current patch (at http://bugs.python.org/issue14588) obtains the explicitly declared metaclass from the keywords dict (exactly like the class statement).

As a static method, the invocation would look like:

 type.buildclass(mcl, bases, keywords, execbody)

So I think, that in theory, this static method could work exactly like the operator.build_class function in the patch: type.build_class(name, bases, kwds, exec_body) (it doesn't need the mcls in a separate argument, it is in kwds).

Since mcl will always be an instance of type in 3.x (due to all classes being subtypes of object), it makes more sense to just make it a class method and invoke the method on the declared metaclass:

 mcl.buildclass(bases, keywords, execbody)

We could do that, but "mcl will always be an instance of type in 3.x" is not strictly true: an arbitrary callable is still allowed as a metaclass in a class statement, so I think the build_class function should support it too.

The following assertion does not hold reliably:

 cls = mcl.buildclass(bases, keywords, execbody)  assert type(cls) == mcl # Not guaranteed

Right.

Instead, the invariant that holds is the weaker assertion:

 cls = mcl.buildclass(bases, keywords, execbody)  assert isinstance(cls, mcl)

But if mcl is an arbitrary callable, this is also not always true (of course, then the invocation above wouldn't work, but with a class statement we could still create such "classes":

def f(mcls, name, bases): ... return 0 ... class C(metaclass=f): ... pass ... C 0

Daniel



More information about the Python-Dev mailing list