Подтвердить что ты не робот

Почему "Нет в numpy.asarray(...)" вызывает будущее предупреждение

Будущее предупреждение происходит, когда вы делаете что-то вроде этого:

>>> numpy.asarray([1,2,3,None]) == None

В настоящее время возвращается False, но я понимаю, что вернет массив, содержащий [False,False,False,True] в будущей версии Numpy.

Как обсуждалось в списке обсуждений numpy, чтобы проверить a is None.

Что меня смущает, так это поведение ключевого слова in с 1D-массивом по сравнению со списком:

>>> None in [1,2,3,None]
True
>>> None in numpy.asarray([1,2,3,None])
__main__:1: FutureWarning: comparison to 'None' will result in an elementwise 
    object comparison in the future
False
>>> 1 in numpy.asarray([1,2,3,None])
True

EDIT (см. комментарии). На самом деле есть два разных вопроса:

  • Почему это вызывает FutureWarning - что будет сравниваться с будущим поведением None in numpy.asarray(...) с тем, что оно сейчас?
  • Почему разница в поведении in от a list; могу ли я проверить, содержит ли мой массив None, не преобразовывая его в список или используя цикл for?

Версия для Numpy - 1.9.1, Python 3.4.1

4b9b3361

Ответ 1

Будущее предупреждение происходит, когда вы делаете что-то вроде этого:

numpy.asarray([1,2,3,4]) == None

В настоящее время возвращается False, но я понимаю, что вернет массив, содержащий [False,False,False,True] в будущей версии Numpy.

Как я уже упоминал в комментариях, ваш пример неверен. Будущие версии numpy вернут [False ,False, False, False], т.е. False для каждого элемента массива, который не равен None. Это в большей степени согласуется с тем, как в настоящее время работают сопоставления элементов с другими скалярными значениями, например:

In [1]: np.array([1, 2, 3, 4]) == 1
Out[1]: array([ True, False, False, False], dtype=bool)

In [2]: np.array(['a', 'b', 'c', 'd']) == 'b'
Out[2]: array([False,  True, False, False], dtype=bool)

Что меня смущает, так это поведение ключевого слова in с 1D-массивом по сравнению со списком

Когда вы тестируете x in y, вы вызываете y.__contains__(x). Когда y - это список, __contains__ в основном что-то делает по строкам:

for item in y:
    if (item is x) or (item == x):
        return True
return False

Насколько я могу судить, np.ndarray.__contains__(x) выполняет эквивалент этого:

if any(y == x):
    return True
else:
    return False

То есть он сначала проверяет элементарное равенство по всему массиву (y == x будет булевым массивом размером y). Поскольку в вашем случае вы проверяете, будет ли y == None, это повысит значение FutureWarning по причинам, указанным выше.

В комментариях вы также хотели знать, почему

np.nan in np.array([1, 2, 3, np.nan])

возвращает False, но

np.nan in [1, 2, 3, np.nan]

возвращает True. Первая часть легко объясняется тем, что np.nan != np.nan (см. Здесь для обоснования этого). Чтобы понять, почему второй случай возвращает True, помните, что list.__contains__() сначала проверяет идентификатор (is) перед проверкой равенства (==). Поскольку np.nan is np.nan, второй случай вернет True.