1
\$\begingroup\$

I want to check if a variable is nan with Python.

I have a working method value != value gives True if value is an nan. However, it is ugly and not so readable. Plus, sonarcloud considers it as a bug for the reason "identical expressions should not be used on both sides of a binary operator".

Do you have a better/elegant solution? Thanks.

import math
import numpy as np

v1 = float('nan')
v2 = math.nan
v3 = np.nan

def check_nan(value) -> bool:
    is_nan =  value != value
    return is_nan

v1_is_nan = check_nan(value=v1)
v2_is_nan = check_nan(value=v2)
v3_is_nan = check_nan(value=v3)

print(v1_is_nan)  # printed True
print(v2_is_nan)  # printed True
print(v3_is_nan)  # printed True
\$\endgroup\$
7
  • \$\begingroup\$ The code as provided doesn't really look like real actual code from a project. Who would use the name check_nan_ugly_method in actual code? \$\endgroup\$
    – Peilonrayz
    Mar 13 '20 at 16:32
  • \$\begingroup\$ @Peilonrayz this is an example code, I have simplified my actual project code to focus on my question. Why do you need my actual project code? \$\endgroup\$
    – aura
    Mar 13 '20 at 16:35
  • 4
    \$\begingroup\$ Please read the help center, specifically the section "Is it actual code from a project rather than pseudo-code or hypothetical code?" Currently the, unhelpful, answer "use better function names" can be a legitimate answer because you chose to change your code to be worse than I assume it is. \$\endgroup\$
    – Peilonrayz
    Mar 13 '20 at 16:39
  • \$\begingroup\$ @Peilonrayz thanks for your info. I did not know this. \$\endgroup\$
    – aura
    Mar 13 '20 at 16:48
  • \$\begingroup\$ @aura You should edit your question. \$\endgroup\$
    – AMC
    Mar 13 '20 at 22:50
6
\$\begingroup\$

Methods for this already exist, particularly because of the weird properties of NaNs. One of them can be found in the math library, math.isnan and numpy already has a method implemented for this as well, numpy.isnan. They both deal with all three kinds of NaNs shown in your code (but the numpy version is vectorized):

import math
import numpy as np

list(map(math.isnan, [float("nan"), math.nan, np.nan]))
# [True, True, True]

np.isnan([float("nan"), math.nan, np.nan]) 
# array([ True,  True,  True])

If you are using pandas, pandas.isna is also interesting because it considers None and pandas.NaT (Not a Time) as missing values as well:

import pandas as pd

pd.isna([float("nan"), math.nan, np.nan, None, pd.NaT])
# array([ True,  True,  True,  True,  True])

Your code has a potential flaw, it does not return True only for NaNs (although it does return True for all NaNs), but for all objects which are not equal to themselves. In particular, it will think any instance of this class is NaN (probably true, but not necessarily):

class A:
    def __equal__(self, other):
        return False
\$\endgroup\$
0
2
\$\begingroup\$

IMHO your function is correct and readable as it is. If I see something like x != x in any language my mind jumps immediately to NaN, regardless of the type. So if you have something like a missing string or date or whatever, this test still makes sense.

Regarding the report from sonarsource. It is always helpful to read the rationale behind a rule. If you look here there are nice examples why this rule generally makes sense. I don't think this applies in your case and you can ignore it.

Some nitpicks:

  1. I would directly return without creating a temporary. The same is true for printing.
  2. There are two spaces after is_nan =
  3. Your functions are not in a class and are really functions. Even if they were methods it would be very redundant to add it. Why don't you just call it is_nan?
import math
import numpy as np

v1 = float('nan')
v2 = math.nan
v3 = np.nan

def is_nan(value) -> bool:
    return value != value

print(is_nan(v1))
print(is_nan(v2))
print(is_nan(v3))
```
\$\endgroup\$
1
  • \$\begingroup\$ thanks for your answer. I like your idea about renaming the function. However, I still think x==x is not so readable for checking nan. \$\endgroup\$
    – aura
    Mar 14 '20 at 14:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.