> On 1 Dec 2017, at 07:01, Nick Coghlan <ncogh...@gmail.com> wrote:
> 
> On 1 December 2017 at 01:23, Ronald Oussoren <ronaldousso...@mac.com> wrote:
>> 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__).
> 
> I think the second point there may actually allow you to resolve the
> first one, by way of making `__getdescriptor__` an optional override
> of the typical lookup algorithm. That is:
> 
>    def _PyType_Lookup(tp, name):
> 
>        # New optional override for descriptor lookups
>        try:
>            # Ordinary attribute lookup, *NOT* a descriptor lookup
>            getdesc = tp.__getdescriptor__
>        except AttributeError:
>            pass
>        else:
>            return getdesc(name)
> 
>        # Default algorithm used in the absence of an override
>        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
> 
> If you did go this way, then we'd want to add a
> "types.getdescriptor(cls, name)" API to expose _PyType_Lookup at the
> Python layer, since "getattr(type(obj), name)" wouldn't be an accurate
> emulation of the algorithm any more.

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.

BTW. getattr(type(obj), name) is not an accurate emulation of _PyType_Lookup 
even now, thanks to metaclasses. In particular:

```
class A_meta (type):
    @property
    def description(self): return "meta description"

    @description.setter
    def description(self, v):
        raise RuntimeError

class A (metaclass=A_meta):

    @property
    def description(self): return "description"

    @description.setter
    def description(self, v):
        raise RuntimeError


a = A()

print(A.description)                    # prints “meta description"
print(a.description)                    # prints “description"
print(getattr(type(a), 'description’))  # prints “meta description"
```

The setter definitions are necessary to ensure that the properties are data 
descriptors, which are handled differently than function descriptors by 
__getattribute__.

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