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/