2

There is the code:

import numpy as np

def check(x):
    if x == None:
        print('x is None')

check(np.array([1,2]))

x can be None or np.ndarray, so I want to check whether x is None or np.ndarray, but if I pass np.ndarray into check, it will raise a error, because np.ndarray==None should use np.any() or np.all(). So what should I do?

gaussclb
  • 1,217
  • 3
  • 13
  • 26
  • 6
    Identity comparison: `if x is None:`. [The answer to this question](https://stackoverflow.com/questions/14247373/python-none-comparison-should-i-use-is-or) mentions your case specifically – objects that override `__eq__` and behave surprisingly when compared to for example None. – Ilja Everilä Sep 19 '17 at 12:22
  • @IljaEverilä You should make this the answer. – Hank Gay Sep 19 '17 at 13:03
  • @HankGay I've tried to find a better dupe target for this, which the link from before almost is, but not quite. – Ilja Everilä Sep 19 '17 at 13:05
  • @IljaEverilä Yeah, I almost closed as a dupe, but I decided that even though the underlying issue was a dupe, this particular manifestation didn't have an obvious one I knew about. If somebody else wants to do that particular legwork, they're welcome to it. Seriously, though: you should make your comment an answer, because it's the root of the actual problem. I'll upvote you. – Hank Gay Sep 19 '17 at 17:07

3 Answers3

1

Try this one:

import numpy as np

def check(x):
    if type(x) is np.ndarray:
        print('x is numpy.ndarray')
    else:
        raise ValueError("x is None")

check(np.array([1, 2]))
Kian
  • 1,319
  • 1
  • 13
  • 23
  • Yes, you're right, however I'm just considering he wants to pass whether a numpy array or None! – Kian Sep 19 '17 at 13:19
1

Checking for ndarray type

Preferred over type(x): use isinstance.

From PEP 8:

Object type comparisons should always use isinstance() instead of comparing types directly.

In your example: use if isinstance(x, np.ndarray):

Checking if x is None

Option 1: Use elif x is None:. This explicitly checks that x is None.

Option 2: Use elif not x:. This takes advantage of the "Falsiness" of None, but it also would evaluate to True if x is other "Falsey" values such as np.nan, 0, or an empty data structure.

Brad Solomon
  • 38,521
  • 31
  • 149
  • 235
0

The reason it raises the value error is that with a recent enough version of Numpy the __eq__ override of arrays does an elementwise object comparison even when comparing to None.

With Numpy 1.12.1:

In [2]: if np.array([1,2,3]) == None:
   ...:     print('Equals None')
   ...: else:
   ...:     print('Does not equal None')
   ...:     
/home/user/Work/SO/bin/ipython:1: FutureWarning: comparison to `None` will result in an elementwise object comparison in the future.
  #!/home/user/Work/SO/bin/python3
Does not equal None

and with Numpy 1.13.1:

In [1]: if np.array([1,2,3]) == None:
   ...:     print('Equals None')
   ...: else:
   ...:     print('Does not equal None')
   ...:     
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-1-06133f6732e1> in <module>()
----> 1 if np.array([1,2,3]) == None:
      2     print('Equals None')
      3 else:
      4     print('Does not equal None')
      5 

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

The error is quite self explanatory. Numpy has a different view on truthiness of an array compared to how plain Python sequences behave.

In order to check if an object is the singleton value None, you should use identity comparison as also explained here:

def check(x):
    if x is None:
        print('x is None')

    else:
        print('x is not None')
Ilja Everilä
  • 50,538
  • 7
  • 126
  • 127