> On 25 Jul 2015, at 17:39, Mark Shannon <m...@hotpy.org> wrote: > > Hi, > > On 22/07/15 09:25, Ronald Oussoren wrote:> Hi, >> >> Another summer with another EuroPython, which means its time again to >> try to revive PEP 447… >> > > IMO, there are two main issues with the PEP and implementation. > > 1. The implementation as outlined in the PEP is infinitely recursive, since > the > lookup of "__getdescriptor__" on type must necessarily call > type.__getdescriptor__. > The implementation (in C) special cases classes that inherit > "__getdescriptor__" > from type. This special casing should be mentioned in the PEP.
Sure. An alternative is to slightly change the the PEP: use __getdescriptor__ when present and directly peek into __dict__ when it is not, and then remove the default __getdescriptor__. The reason I didn’t do this in the PEP is that I prefer a programming model where I can explicitly call the default behaviour. > > 2. The actual implementation in C does not account for the case where the > class > of a metaclass implements __getdescriptor__ and that method returns a value > when > called with "__getdescriptor__" as the argument. Isn’t that the same problem as with all slots, even when using __getattribute__? That is, a meta class that implements __getattribute__ to return implementations for (say) __getitem__ won’t work because the interpreter won’t call __getattribute__ to get that implementation unless it already knows that the attribute is present. Class creation, and __setattr__ on type will not only fill __dict__, but also set slots in the type structure as appropriate. The interpreter than uses those slots to determine if a special method is present. In code: class Meta1 (type): def __getitem__(self, key): return "<{} {}>".format(self.__name__, key) class Class1 (metaclass=Meta1): pass class Meta2 (type): def __getattribute__(self, name): if name == "__getitem__": return lambda key: "<{} {}>".format(self.__name__, key) return super().__getattribute__(name) class Class2 (metaclass=Meta2): pass print(Class1.__getitem__("hello")) print(Class1["hello"]) print(Class2.__getitem__("hello")) print(Class2["hello"]) The last line causes an exception: Traceback (most recent call last): File "demo-getattr.py", line 24, in <module> print(Class2["hello"]) TypeError: 'Meta2' object is not subscriptable I agree that this should be mentioned in the PEP as it can be confusing. > > > > Why was "__getattribute_super__" rejected as an alternative? No reason is > given. > > "__getattribute_super__" has none of the problems listed above. Not really. I initially used __getattribute_super__ as the name, but IIRC with the same semantics. > Making super(t, obj) delegate to t.__super__(obj) seems consistent with other > builtin method/classes and doesn't add corner cases to the already complex > implementation of PyType_Lookup(). A disadvantage of delegation is t.__super__ then reproduce the logic dealing with the MRO, while my proposal allows the metaclass to just deal with lookup in a specific class object. Implementation complexity is an issue, but it seems to be acceptable so far. The main problem w.r.t. additional complexity is that PyType_Lookup can now fail with an exception other than an implied AttributeError and that causes changes elsewhere in the implementation. BTW. The patch for that part is slightly uglier than it needs to be, I currently test for PyErr_Occurred() instead of using return codes in a number of places to minimise the number of lines changes to make code review easier. That needs to be changed before the code would actually be committed. Ronald P.S. Are you at the EP sprints? I’ll be there until early in the afternoon. > > Cheers, > Mark > _______________________________________________ > Python-Dev mailing list > Python-Dev@python.org > https://mail.python.org/mailman/listinfo/python-dev > Unsubscribe: > https://mail.python.org/mailman/options/python-dev/ronaldoussoren%40mac.com
_______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com