[Python-Dev] Adding types.build_class for 3.3
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.build_class(mcl, bases, keywords, exec_body)
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.build_class(bases, keywords, exec_body)
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.build_class(bases, keywords, exec_body)
> assert type(cls) == mcl # Not guaranteed
Right.
> Instead, the invariant that holds is the weaker assertion:
>
> cls = mcl.build_class(bases, keywords, exec_body)
> 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