Author gvanrossum
Recipients amaury.forgeotdarc, benjamin.peterson, daniel.urban, georg.brandl, gvanrossum, ncoghlan, pwerneck, rodsenra, terry.reedy
Date 2011-04-20.20:22:31
SpamBayes Score 1.86074e-09
Marked as misclassified No
Message-id <1303330952.82.0.328442792697.issue1294232@psf.upfronthosting.co.za>
In-reply-to
Content
class X(metaclass=func) should definitely continue to work; that is a long-standing (if relatively unknown, and very advanced) feature. In fact, metaclasses have their origins in this, via the "Don Beaudry hook" -- see http://python-history.blogspot.com/2009/04/metaclasses-and-extension-classes-aka.html .

IMO we should also keep class X(object, metaclass=func) working; it should just construct a tuple of bases (object,) and pass it to func.

I realize there is now a circular dependency: you need the metaclass computation in order to find the metaclass and you need the metaclass in order to find the prepare hook, but you need to call the prepare hook before you call the metaclass and hence before the metaclass computation is carried out.  I'm not sure how to reconcile that but I think we should look harder rather than give up.

As to how PEP 3115 seems to imply that all classes derive from object, that only applies as long as their metaclass is (derived from) type.  And that is in a sense a tautology since (dynamically) we only call something a class if its metaclass is (derived from) type.  However the class statement does not necessarily create a class object!  It creates whatever the metaclass creates, with suitable defaults: if there's no explicit metaclass, look at the class of the first given base; if no bases are given either, use object.  But an explicit metaclass should win.

Maybe the metaclass computation (which should come up with the "most derived" metaclass if there are multiple bases or bases and a metaclass) is something that we can give a name as another attribute on the "initial" metaclass, and a suitable default?  Let's say __compute_metaclass__(tuple_of_bases).  The default could be the initial metaclass, and type could override it to do the correct computation (which computes the most derived metaclass, and raises an error if any of the bases has a metaclass that is not in the answer's ancestor).  Then this computation could run before we get __prepare__ (from the answer).  When metaclass=func is given one could have __prepare__ as a function attribute and even the __compute_metacass__ could be overridden as a function attribute, so everything is still fully general.

[Sorry for blathering on. Not feeling great.]
History
Date User Action Args
2011-04-20 20:22:32gvanrossumsetrecipients: + gvanrossum, georg.brandl, terry.reedy, amaury.forgeotdarc, ncoghlan, rodsenra, pwerneck, benjamin.peterson, daniel.urban
2011-04-20 20:22:32gvanrossumsetmessageid: <1303330952.82.0.328442792697.issue1294232@psf.upfronthosting.co.za>
2011-04-20 20:22:32gvanrossumlinkissue1294232 messages
2011-04-20 20:22:31gvanrossumcreate