On Sat, Jul 12, 2014 at 8:37 AM, Cameron Simpson <c...@zip.com.au> wrote: > On 11Jul2014 14:37, Chris Angelico <ros...@gmail.com> wrote: >> >> Does C-level code have to check this flag before comparing >> nans, > > > If you mean: > > float x, y; > [...] > if (x == y) { > action... > } > > then no. > > >> or is this applicable only to the Python float objects and only >> when compared in Python? > > > The former but not the latter, in my mind. Comparing Python float objects > should obey the rule, whether in pure Python or extensions using a PyFloat. > But I'd hope they get that for free by indirecting through PyFloat's > methods.
Suppose you have some C extension that works with numbers (I have NumPy in mind as I write this, but I'm not familiar with its inner workings; certainly it'd be possible for this to be implemented how I describe). You pack a bunch of Python float objects into an array, pack another bunch into another array, and then compare them. >>> from numpy import array >>> x=array([1.0,2.0]) >>> y=array([1.0,2.1]) >>> x==y array([ True, False], dtype=bool) So far, so good. Now let's introduce a NaN. >>> nan=float("nan") >>> x=array([1.0,2.0,nan]) >>> y=array([1.0,2.1,nan]) >>> x==y array([ True, False, False], dtype=bool) I deliberately used the exact same nan so that an identity or bit-pattern check would return True; but numpy says False, these are not the same. Now, if I replace array with this list-like thing, then your context manager would control that last result: >>> class array(list): def __eq__(self, other): if not isinstance(other, type(self)) or len(other)!=len(self): return False return [self[i] == other[i] for i in range(len(self))] But if, instead, the array is packed into a C-level array of floats (which can be done without losing any information other than object identity), then this would no longer be affected by your context manager, unless the extension unnecessarily reconstructs two Python floats to compare them, or else is made specifically aware of the change. >> Is isnan() still usable? > > Yes. > >> (Consider that x!=x == math.isnan(x) normally.) > > Can you elaborate on this statement please? def isnan(x): return isinstance(x, float) and x!=x Fairly standard way of defining isnan(). It would be extremely surprising if that correlation didn't work. Let's suppose you want to sort a list of floats with all NaNs coming first: new_list = sorted(old_list, key=lambda x: (x==x, x)) new_list = sorted(old_list, key=lambda x: (not math.isnan(x), x)) The first one is much briefer (and faster, as it doesn't need to look up math and math.isnan and then call a function), and people will assume they're equivalent. If this kind of thing happens deep inside a call tree, it'll be extremely surprising that the two act differently. So there has to be some other way to implement isnan(), which will probably involve poking around with the bit pattern, and everyone MUST use that instead of the simple comparison. ChrisA -- https://mail.python.org/mailman/listinfo/python-list