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/