Message289470
> 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) |
|
Date |
User |
Action |
Args |
2017-03-12 04:13:27 | eryksun | set | recipients:
+ eryksun, tim.peters, vstinner, serhiy.storchaka, ppperry, mdk, elliot.gorokhovsky |
2017-03-12 04:13:27 | eryksun | set | messageid: <1489292007.1.0.754585357181.issue28685@psf.upfronthosting.co.za> |
2017-03-12 04:13:27 | eryksun | link | issue28685 messages |
2017-03-12 04:13:25 | eryksun | create | |
|