Is duck typing float or Decimal worth the bother? Barring that it could be
done with some isinstance() checks (in the user code, not in math.isnan()).

Otherwise, your only resort is a PEP, like the final comment of that bug
says.

On Fri, Dec 27, 2019 at 18:16 David Mertz <me...@gnosis.cx> wrote:

> Great work! I had not known if those corners.
>
> Have you tried with NumPy zero-D arrays or PyTorch Values? Both of those
> should have sensible answers.
>
> On Fri, Dec 27, 2019, 7:42 PM Steven D'Aprano <st...@pearwood.info> wrote:
>
>> By the way, it's not as easy as you might think to test whether a value
>> is a NAN or not.
>>
>> There are currently three ways to test whether a value is a NAN. (Four
>> if you include cmath.isnan.)
>>
>> 1. math.isnan(x) but it can fail in annoying ways.
>>
>>
>>     # No int is a NAN so this should return False
>>     py> math.isnan(10**1000)
>>     Traceback (most recent call last):
>>       File "<stdin>", line 1, in <module>
>>     OverflowError: int too large to convert to float
>>
>>     # Decimal signalling NANs are NANs so this should return True
>>     py> x = Decimal('snan')
>>     py> math.isnan(x)
>>     Traceback (most recent call last):
>>       File "<stdin>", line 1, in <module>
>>     ValueError: cannot convert signaling NaN to float
>>
>>
>> 2. Decimal.is_nan() but it only works with decimals. However it does
>> work with signalling NANs.
>>
>>
>> 3. Back before math.isnan existed, the idiomatic way to check for NANs
>> was to test whether they were equal to themselves. Assuming that x is a
>> kind of numeric type, we should expect that `x == x` except for NANs.
>> But this too fails for signalling NANs:
>>
>>
>>     # Using the default Decimal context
>>     py> x == x
>>     Traceback (most recent call last):
>>       File "<stdin>", line 1, in <module>
>>     decimal.InvalidOperation: [<class 'decimal.InvalidOperation'>]
>>
>>
>> So there is no good way to check for an arbitrary NAN that duck-types
>> floats, Decimals, ints, Fractions and other numeric types.
>>
>> I have come up with this:
>>
>>
>>     def isnan(x, _isnan=math.isnan):
>>         try:
>>             return _isnan(x)
>>         except ValueError:
>>             # Could be a Decimal signalling NAN.
>>             try:
>>                 return x.is_nan()
>>             except AttributeError:
>>                 return x != x
>>         except OverflowError:
>>             return False
>>         except TypeError:
>>             from cmath import isnan
>>             return isnan(x)
>>
>>
>> but I fear that there could be other landmines waiting, other odd corner
>> cases I haven't thought of.
>>
>> See also
>>
>> https://bugs.python.org/issue27975
>>
>>
>>
>> --
>> Steven
>> _______________________________________________
>> Python-ideas mailing list -- python-ideas@python.org
>> To unsubscribe send an email to python-ideas-le...@python.org
>> https://mail.python.org/mailman3/lists/python-ideas.python.org/
>> Message archived at
>> https://mail.python.org/archives/list/python-ideas@python.org/message/VHC4GO37ZT2UEW6RSRF4ASMTVK52UQ6H/
>> Code of Conduct: http://python.org/psf/codeofconduct/
>>
> _______________________________________________
> Python-ideas mailing list -- python-ideas@python.org
> To unsubscribe send an email to python-ideas-le...@python.org
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at
> https://mail.python.org/archives/list/python-ideas@python.org/message/AGBORBUDM2763CORRJBJPDCOJ3TSNNA5/
> Code of Conduct: http://python.org/psf/codeofconduct/
>
-- 
--Guido (mobile)
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/OGU3QD6PEFZ3BTZYQDMC4SB6FVLRKP6B/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to