> On 1 Dec 2017, at 07:01, Nick Coghlan <[email protected]> wrote:
>
> On 1 December 2017 at 01:23, Ronald Oussoren <[email protected]> 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
[email protected]
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/