[Python-ideas] A way out of Meta-hell (was: A (meta)class algebra) (original) (raw)

Nick Coghlan ncoghlan at gmail.com
Thu Feb 19 12:10:05 CET 2015


On 18 Feb 2015 18:51, "Martin Teichmann" <lkb.teichmann at gmail.com> wrote:

> Zope already implements classinit via a metaclass, so I'm not clear on > how this addition would help with a backport of the initclass spelling > to Python 2. Well, there is just a small issue in the zope implementation. They don't support super(). So you cannot write: from ExtensionClass import Base class Spam(Base): def classinit(self): super().classinit(self) # this line raises RuntimeError # do something here The precise error is: RuntimeError: super(): empty class cell My pure python implementation with initsubclass support super() without problems. The problem is that at the point they call classinit (at the end of ExtensionClass.new) the class in the methods is not initialized yet. Interestingly, it also doesn't help to move that call into init, which is still a mystery to me, I was under the assumtion that at the point of init the class should be fully initialized. Interestingly, type manages to set the class of the methods AFTER init has finished. How it manages to do so I don't know, but probably that's special-cased in C.

Yes, populating class happens inside the interpreter only after the class is fully constructed, so even though the class is fully initialised at the end of init, a reference hasn't been inserted into the cell yet. (The class cell doesn't actually live on the class object - it's created implicitly by the interpreter and then referenced from the individual methods as a closure variable for each method that looks up "class" or "super")

Python 2 doesn't provide the implicitly populated class_ cell at all though, so you have to refer to the class object by its name - zero argument super is a Python 3 only feature.

> I agree a clean idiom for detecting whether you're in the base class or not > might be useful, but even without specific support in the PEP you'll at > least be able to do that either by inspecting the MRO, or else by assuming > that the class name not being bound yet means you're still in the process of > creating it.

That sounds very complicated to me. Could you please give me an example how I am supposed to do that?

Second one is fairly straightforward - either do a check for the class name in the module globals() or catching the resulting NameError. Checking the MRO would be a bit more fragile, and likely not worth fiddling with given the ability to check for the name binding of the base class directly.

You also have the option of just setting an initialisation flag on the class object itself (since the initial execution in the base class will always be the first execution).

Cheers, Nick. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.python.org/pipermail/python-ideas/attachments/20150219/39e4917a/attachment.html>



More information about the Python-ideas mailing list