Never mind... the cases I mentioned are happy already: >>> import numpy as np >>> import torch >>> import math >>> math.isnan(np.nan), type(np.nan) (True, <class 'float'>) >>> np_nan = np.array(np.nan) >>> math.isnan(np_nan), type(np_nan) (True, <class 'numpy.ndarray'>) >>> torch_nan = torch.Tensor([float('nan')]) >>> math.isnan(torch_nan), type(torch_nan) (True, <class 'torch.Tensor'>)
Interestingly: >>> np_nans = np.array([np.nan, np.nan]) >>> math.isnan(np_nans) Traceback (most recent call last): File "<ipython-input-26-2f5da5ba4604>", line 1, in <module> math.isnan(np_nans) TypeError: only size-1 arrays can be converted to Python scalars >>> torch_nans = torch.Tensor([float('nan'), np.nan]) >>> torch_nans tensor([nan, nan]) >>> math.isnan(torch_nans) Traceback (most recent call last): File "<ipython-input-22-72715a2d3347>", line 1, in <module> math.isnan(torch_nans) ValueError: only one element tensors can be converted to Python scalars And yet: >>> np_nan_arr = np.array([np.nan]).reshape(1, 1, 1, 1) >>> math.isnan(np_nan_arr), np_nan_arr.shape (True, (1, 1, 1, 1)) So it's really only the 1-element-ness being checked, not the 0-D shape. On Fri, Dec 27, 2019 at 8:14 PM 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/ >> > -- Keeping medicines from the bloodstreams of the sick; food from the bellies of the hungry; books from the hands of the uneducated; technology from the underdeveloped; and putting advocates of freedom in prisons. Intellectual property is to the 21st century what the slave trade was to the 16th.
_______________________________________________ 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/4KBOOPUES66FCHAYIKVORJB7IBRUEEDW/ Code of Conduct: http://python.org/psf/codeofconduct/