Hi,

I’m trying to get up to speed again w.r.t. PEP 447 (and to be honest, with CPython’s development workflow as its been too long since I’ve actually done work on the CPython codebase…).

Let me start by recapping the PEP (<https://www.python.org/dev/peps/pep-0447/>) is about: The problem I’m trying to solve is that super.__getattribute__ basicy assumes looking at the __dict__ of classes on the MRO is all that’s needed to check if those classes provide an attribute.  The core of both object.__getattribute__ and super.__getattribute__ for finding a descriptor on the class is basically (from the PEP):

def _PyType_Lookup(tp, name):
        mro = tp.mro()
        assert isinstance(mro, tuple)

        for base in mro:
           assert isinstance(base, type)

           try:
               return base.__dict__[name]
           except KeyError:
               pass

        return None

Note that the real implementation in in C, and accesses base.__dict__ directly instead of through Python’s attribute lookup (which would lead to infinite recursion).

This is problematic when the class is dynamically populated, as the descriptor may not yet be present in the class __dict__.  This is not a problem for normal attribute lookup, as you can replace the __getattribute__ method of the class to do the additional work (at the cost of having to reimplement all of __getattribute__).  This is a problem for super() calls though, as super will unconditionally use the lookup code above.

The PEP proposed to replace “base.__dict__[name]” by “base.__class__.__getdescriptor__(name)” (once again, in C with direct access to the two slots instead of accessing them through normal attribute lookup).

I have two open questions about this PEP:

1) Last time around Mark Shannon worried that this introduces infinite recursion in the language itself (in my crummy summary, please read this message to get the real concern <https://mail.python.org/pipermail/python-dev/2015-July/140938.html>).  Is this truly a problem?  I don’t think there is a problem, but I’m worried that I don’t fully understand Mark’s concerns.

2) PEP 487 introduced __init_subclass__ as a class method to avoid having to write a metaclass for a number of use cases.  My PEP currently does require a metaclass, but it might be nicer to switch to a regular class method instead (like __init_subclass__). 

My primary usecase for this PEP is PyObjC, which does populate the class dictionary on demand for performance and correctness reasons and PyObC therefore currently includes a replacement for super.  For PyObjC’s implementation making __getdescriptor__ a classmethod would be a win as this would avoid creating yet another level of metaclasses in C code (PyObjC already has a Python class and metaclass for every Objective-C class, PEP 447 would require the introduction of a metaclass for those metaclasses). 

BTW. Two other open issues w.r.t. this PEP are forward porting the patch (in issue 18181) and performing benchmarks. The patch doesn’t apply cleanly to the current tip of the tree, I’ll try to update it tomorrow.  And with some luck will manage to update PyObjC’s implementation as well to validate the design.

Ronald