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/ 
<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 
<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
_______________________________________________
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to