On Sun, 08 Jun 2014 18:56:47 +0300, Marko Rauhamaa wrote: > Paul Sokolovsky <pmis...@gmail.com>: > >> Python already has that - like, len(x) calls x.__len__() if it's >> defined > > In fact, what's the point of having the duality? > > len(x) <==> x.__len__() > > x < y <==> x.__lt__(y) > > str(x) <==> x.__str__()
Interface on the left, implementation on the right. That's especially obvious when you consider operators like < + - * etc. Consider x + y. What happens? #1 First, Python checks whether y is an instance of a *subclass* of x. If so, y gets priority, otherwise x gets priority. #2 If y gets priority, y.__radd__(x) is called, if it exists. If it returns something other than NotImplemented, we are done. #3 However if y.__radd__ doesn't exist, or it returns NotImplemented, then Python continues as if x had priority. #3 If x has priority, then x.__add__(y) is called, if it exists. If it returns something other than NotImplemented, we are done. #4 However if it doesn't exist, or it returns NotImplemented, then y.__radd__(x) is called, provided it wasn't already tried in step #2. #5 Finally, if neither object has __add__ or __radd__, or both return NotImplemented, then Python raises TypeError. That's a lot of boilerplate if you were required to implement it yourself in every single operator method. Better, Python handles all the boiler plate, all you have to do is just handle the cases you care about, and return NotImplemented for everything else. -- Steven D'Aprano http://import-that.dreamwidth.org/ -- https://mail.python.org/mailman/listinfo/python-list