Eryk Sun added the comment:

> assignment of "__lt__" change the value of the tp_richcompare slot? 

Yes. CPython doesn't implement individual dispatching of the rich-comparison 
functions. There's a single tp_richcompare slot, so overriding one rich 
comparison forces the use of slot_tp_richcompare. For built-in types this 
incurs the performance penalty of using a wrapper_descriptor for the other rich 
comparisons. For example, overriding F.__lt__ forces calling float.__gt__ for 
the greater-than comparison. 

Before:

    >>> F() > 1

    Breakpoint 0 hit
    python37_d!float_richcompare:
    00000000`6099d930 4489442418      mov     dword ptr [rsp+18h],r8d
                                              ss:00000056`cefef280=a1670058
    0:000> kc 3
    Call Site
    python37_d!float_richcompare
    python37_d!do_richcompare
    python37_d!PyObject_RichCompare
    0:000> g
    False

After:

    >>> F.__lt__ = lambda a, b: 0
    >>> F() > 1

    Breakpoint 0 hit
    python37_d!float_richcompare:
    00000000`6099d930 4489442418      mov     dword ptr [rsp+18h],r8d
                                              ss:00000056`cefef0a0=a39d7c70
    0:000> kc 9
    Call Site
    python37_d!float_richcompare
    python37_d!wrap_richcmpfunc
    python37_d!richcmp_gt
    python37_d!wrapper_call
    python37_d!_PyObject_FastCallDict
    python37_d!call_unbound
    python37_d!slot_tp_richcompare
    python37_d!do_richcompare
    python37_d!PyObject_RichCompare

The __gt__ wrapper_descriptor gets bound as a method-wrapper, and the 
method-wrapper tp_call is wrapper_call, which calls the wrapper function (e.g. 
richcmp_gt) with the wrapped function (e.g. float_richcompare). The object ID 
in CPython is the object address, so we can easily get the address of the 
__gt__ wrapper_descriptor to confirm how these C function pointers are stored 
in it:

    >>> id(vars(float)['__gt__'])
    2154486684248

    0:001> ln @@(((PyWrapperDescrObject *)2154486684248)->d_base->wrapper)
    (00000000`60a20580)   python37_d!richcmp_gt   |
    (00000000`60a205c0)   python37_d!slot_tp_finalize
    Exact matches:
        python37_d!richcmp_gt (struct _object *, struct _object *, void *)

    0:001> ln @@(((PyWrapperDescrObject *)2154486684248)->d_wrapped)
    (00000000`6099d930)   python37_d!float_richcompare   |
    (00000000`6099e6f0)   python37_d!float_getzero
    Exact matches:
        python37_d!float_richcompare (struct _object *, struct _object *, int)

----------
nosy: +eryksun

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue28685>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to