On Wed, Jan 7, 2015 at 2:39 PM, Dave Angel <da...@davea.name> wrote: > Here we need help from someone who knows more about this particular detail. > I don't know which special methods bool() or not will call, but I'd think it > would be something with a better name than __nonzero__
In Python 2, it is indeed __nonzero__, but in Python 3, it's __bool__: Python 2.7.3 (default, Mar 13 2014, 11:03:55) [GCC 4.7.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> class X: ... def __nonzero__(self): print("called") ... >>> bool(X()) called Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: __nonzero__ should return an int Python 3.5.0a0 (default:1c51f1650c42+, Dec 29 2014, 02:29:06) [GCC 4.7.2] on linux Type "help", "copyright", "credits" or "license" for more information. >>> class X: ... def __bool__(self): print("called") ... >>> bool(X()) called Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: __bool__ should return bool, returned NoneType Also, as you can see, Py2's method allows any integer to be returned, while Py3's expects a bool. The boolification of an object MUST result in either True or False, nothing else. >> Question: If two different class's instances are being compared by >> '==', and both define an __eq__ method, which method gets called? ( I >> don't know if that applied here... but I'm not familiar with order of >> operations ) > > > The left object's methods are generally examined first. So if you said > mylist * 5 > > you'd be using a __mul__ method of list class. Order of operations has nothing to do with this; that's to do with operator precedence/associativity, which is what stipulates that all of these parentheses are unnecessary: a + (b * c) (a + b) + c a ** (b ** c) a or (b and c) (a + b) in c a if (b + c) else d The operator precedence tables neither know nor care what the objects in question are. But once the interpreter gets to the next step, and starts actually figuring out the value of the expression, then it usually goes for the left object's methods first; if that object returns NotImplemented, it'll try the right object (sometimes with a reflected method): >>> class X: ... def __eq__(self, other): print("Am I equal to:",other) ... def __add__(self, other): print("me +",other) ... def __radd__(self, other): print(other,"+ me") ... >>> X() == 1 Am I equal to: 1 >>> 2 == X() Am I equal to: 2 >>> X() + 3 me + 3 >>> 4 + X() 4 + me >> But I don't think that stops me from treating the sort order of all >> items which are quasi-equal, as a second search (hierarchical search). >> eg: Sort first by definite magnitude, then among those deemed 'equal', >> sort them by average expectation value... That's going to be good >> enough for me and my users, for the sort order of truly quasi equal >> things is arbitrary anyway... as long as it's not 'defintely wrong' >> they'll have no reason to complain. > > > You could write a sort that works that way, but I don't think you can assume > that the built-in sort will. sort assumes that the comparison works in a > certain way, and if it doesn't, the symptoms could range from random > ordering (including items drastically out of order) to a possibly never > terminating sort. If you can separate the value into two parts, magnitude and expectation, you could have a key function that makes them sortable: def mag_exp(val): if not isinstance(val, MagicFloat): return (val, None) return int(val), val-int(val) # example srtlst = sorted(lst, key=mag_exp) That'll sort all elements by the first value in the tuple, and if they're identical on that, by the second value. That's the easiest way to do a multi-part sort. ChrisA -- https://mail.python.org/mailman/listinfo/python-list