My time is short, so thank you for focusing on the real subject.

On Mon, 16 Aug 2021 at 11:00, Jeff Allen <ja...@farowl.co.uk> wrote:
> I have spent a lot of time reading typeobject.c over the years I've been 
> looking at an alternative implementation. It's quite difficult to follow, and 
> full of tweaks for special circumstances. So I'm impressed with the 
> understanding that "user2357112 supports Monica" brings to the subject.

I was impressed too. I suppose it worked on some C Extension and
discovered the behaviour herself.

> When a built-in type like dict is defined in C, pointers to its C 
> implementation functions are hard-coded into slots in the type object. In 
> order to make each appear as a method to Python, a descriptor is created when 
> building the type that delegates to the slot (so sq_contains generates a 
> descriptor __contains__ in the dictionary of the type.
>
> Conversely, if in a sub-class you define __contains__, then the type builder 
> will insert a function pointer in the slot of the new type that arranges a 
> call to __contains__. This will overwrite whatever was in the slot.
>
> In a C implementation, you can also define methods (by creating a PyMethodDef 
> the tp_methods table) that become descriptors in the dictionary of the type. 
> You would not normally define both a C function to place in the slot *and* 
> the corresponding method via a PyMethodDef. If you do, the version from the 
> dictionary of the type will win the slot, *unless* you mark the method 
> definition (in its PyMethodDef) as METH_COEXIST.
>
> This exception is used in the special case of dict (and hardly anywhere else 
> but set I think). I assume this is because some important code calls 
> __contains__ via the descriptor, rather than via the slot (which would be 
> quicker), and because an explicit definition is faster than a descriptor 
> created automatically to wrap the slot.
>
> Now, when you create a sub-class, the table of slots is copied first, then 
> the type is checked for definitions of special methods, and these are allowed 
> to overwrite the slot, unless they are slot wrappers on the same function 
> pointer the slot already contains. I think at this point the slot is 
> re-written to contain a wrapper on __contains__, which has been inherited 
> from dict.__contains__, because it isn't a *slot wrapper* on the same 
> function. For example:
>
> >>> dict.__contains__
> <method '__contains__' of 'dict' objects>
> >>> str.__contains__
> <slot wrapper '__contains__' of 'str' objects>
>
> >>> class S(str): pass
>
> >>> S.__contains__
> <slot wrapper '__contains__' of 'str' objects>
> >>> D.__contains__
> <method '__contains__' of 'dict' objects>

And is it not possible for subclasses to continue to use the optimized
version, if some contract will be maintained?
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/UGBL62CDO2XYXAVK6RAOS46ORGL545MV/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to