On Fri, 9 Jun 2017 02:13 pm, Lawrence D’Oliveiro wrote: > On Sunday, June 4, 2017 at 9:59:11 AM UTC+12, Sean DiZazzo wrote: >> Looking at operator precedence, I only see the % operator in regards to >> modulus. Nothing in regards to string formatting. > > Operators in Python have no intrinsic meaning. They are just syntactic sugar > for invoking methods with special names on the operand objects.
That's wrong. The dunder methods are implementation, and are not intended to be called directly. It is a myth that, for example: > For example, > > a % b > > is just a cleaner way of writing > > a.__mod__(b) > > or, if object “a” does not support “__mod__”, but object “b” has “__rmod__”, > then it means > > b.__rmod__(a) That's wrong. First error: in CPython 3, and in CPython 2 for new style classes, the interpreter does not call a.__mod__ or b.__rmod__. Instead, it calls type(a).__mod__ or type(b).__rmod__, which is not necessarily the same thing. Second error: it is not correct that b.__rmod__ is only called if a does not support __mod__. That is a woefully incomplete description of what actually occurs. Here is an approximate pseudo-code of what actually happens: A = type(a) B = type(b) if issubclass(B, A) and hasattr(B, '__rmod__'): x = B.__rmod__(b, a) if x is NotImplemented: if hasattr(A, '__mod__'): x = A.__mod__(a, b) if x is NotImplemented: raise TypeError else: return x else: return x elif hasattr(A, '__mod__'): x = A.__mod__(a, b) if x is NotImplemented: if hasattr(B, '__rmod__'): x = B.__mod__(b, a) if x is NotImplemented: raise TypeError else: return x else: return x elif hasattr(B, '__rmod__'): x = B.__rmod__(b, a) if x is NotImplemented: assert not hasattr(A, '__mod__') raise TypeError else: return x else: raise TypeError The bottom line is, if you are calling dunder methods directly instead of operators, you're probably doing it wrong. -- Steve “Cheer up,” they said, “things could be worse.” So I cheered up, and sure enough, things got worse. -- https://mail.python.org/mailman/listinfo/python-list