> On 1 Dec 2017, at 11:32, Nick Coghlan <ncogh...@gmail.com> wrote: > > On 1 December 2017 at 19:15, Ronald Oussoren <ronaldousso...@mac.com> wrote: > >> Maybe, but how would this work with super()? Super walks the MRO of type of >> the instance, but skips the class on the MRO. This is not equivalent to >> walking the MRO of the second class on the MRO when you use multiple >> inheritance, >> >> This also has some other disadvantages. The first is that >> tp.__getdescriptor__ would replace the default behaviour for the entire MRO >> and it would be possible to have different behavior for classes on the MRO. >> The second, minor. one is that __getdescriptor__ would have to reimplement >> the default logic of walking the MRO, but that logic is fairly trivial. > > I believe those can both be addressed by structuring the override a > little differently, and putting it at the level of individual > attribute retrieval on a specific class (rather than on all of its > subclasses): > > def _PyType_Lookup(tp, name): > mro = tp.mro() > assert isinstance(mro, tuple) > > for base in mro: > assert isinstance(base, type) > > try: > getdesc = base.__dict__["__getdescriptor__"] > except KeyError: > try: > return base.__dict__[name] > except KeyError: > pass > else: > try: > return getdesc(tp, base, name) > except AttributeError: > pass > > return None > > In that version, the __getdescriptor__ signature would be: > > def __getdescriptor__(dynamic_cls, base_cls, attr): > …
That’s basically what’s in the PEP, except that the PEP says that type will implement __getdescriptor__ to make cooperative subclassing easier. The current patch inlines type.__getdescriptor__ in the lookup code for efficiency reasons (that is, the runtime cost for not using this feature is basically a pointer test instead of a function call), but would work just as well without inlining. I’m pretty sure that the first concern isn’t really there, in the end attribute/descriptor resolution ends up in object and type whose implementation must be magic in some way, even without this PEP. The second question is more a design question: what’s the better design, having __getdescriptor__ as a class method on classes or as method on metaclasses? Either one would work, but a class method appears to be easier to use and with the introduction of __init_subclass__ there is a precedent for going for a class method. The current PEP claims that a method on a metaclass would be better to avoid subtle problems, but ignores the conceptual cost of adding a metaclass. The subtle problem is that a class can have two direct superclasses with a __getdescriptor__ when using multiple inheritance, but that can already be an issue for other methods and that currently includes __getattribute__ for most of not all usecases where __getdescriptor__ would be useful. 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/