Josh Rosenberg added the comment:

I'd assume the preference for __rop__ only on subclass overload is because 
__rop__ method are usually fallback methods, and differ behaviorally from the 
__op__ methods in type strictness.

In particular, the __rop__ fallbacks are often so non-strict that they return a 
completely different type; fractions.Fraction.__rop__ is willing to coerce 
itself and the other operand to float and produce a float result if the other 
operand is a numbers.Real (and not a Rational). They also tend to be slower 
(checking against ABCs and doing more type coercion) than the __op__ path.

If you jump straight to __rop__ because the right hand side is a subclass, but 
the subclass didn't overload it, you end up going through that fallback, 
assumed extra liberal and slow, code path.

It doesn't work this way with comparison operators because those are 100% 
reflexive; there is no expectation that comparing in one direction will be more 
or less type permissive than comparing in the other direction (stuff like 
__rcmp__ has been gone for ages after all), so unconditionally comparing using 
the child class comparator first is fine, and more likely to get correct 
results.

The design pattern that has problems here is a bit unorthodox to start with. It 
assumes that the child class constructor will work exactly the same as the 
parent (no additional mandatory arguments for instance), and that it's always 
correct for parent + child to produce the type of child. Usually, in an OO 
design, the parent is not supposed to have any specific knowledge of children; 
it's the job of the children to work with instances of the parent, if 
necessary. If delegation to the child is desired, implement __op__ with 
stricter type checking (to preclude subclasses) and __rop__ with relaxed type 
checking (to allow them); when the __op__ executes, it will return 
NotImplemented for the child class, then delegate to __rop__, which will use 
the child's type.

----------
nosy: +josh.r

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

Reply via email to