On 18 Feb 2015 18:51, "Martin Teichmann" <lkb.teichmann@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 __init_class__ 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 __class_init__(self): super().__class_init__(self) # this line raises RuntimeError # do something here
The precise error is: RuntimeError: super(): empty __class__ cell
My pure python implementation with __init_subclass__ support super() without problems.
The problem is that at the point they call __class_init__ (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.
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
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. 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.