web-dev-qa-db-ja.com

演算子、float( "NaN")およびnp.nan

私は、Pythonのin演算子は、等価チェック_==_を使用して、コレクション内の要素の存在をチェックするので、_element in some_list_はほぼany(x == element for x in some_list)。例:

_True in [1, 2, 3]
# True because True == 1
_

または

_1 in [1., 2., 3.]
# also True because 1 == 1.
_

ただし、NaNがそれ自体と等しくないことはよく知られています。したがって、float("NaN") in [float("NaN")]Falseであると予想しました。そして、それは確かにFalseです。

ただし、float("NaN")の代わりに_numpy.nan_を使用する場合、状況はまったく異なります。

_import numpy as np
np.nan in [np.nan, 1, 2]
# True
_

しかし、_np.nan == np.nan_はまだFalseを与えます!

どうして可能ですか? _np.nan_とfloat("NaN")の違いは何ですか? inは_np.nan_をどのように処理しますか?

27
Ilya V. Schurov

アイテムがリストにあるかどうかを確認するには、Pythonオブジェクトの同一性をテストfirst、次に等価性のみをテストオブジェクトが異なる場合。1

2つのdifferentNaNオブジェクトが比較に関係するため、float("NaN") in [float("NaN")]はFalseです。したがって、同一性のテストはFalseを返します。また、NaN != NaN

np.nan in [np.nan, 1, 2]ただし、sameNaNオブジェクトが比較に関係しているため、Trueです。オブジェクトIDのテストはTrueを返すので、Pythonはアイテムがリストにあるとすぐに認識します。

__contains__メソッド(inを使用して呼び出されます)は、タプルやセットなど、Pythonのその他の多くの組み込みコンテナタイプの多くで、同じチェックを使用して実装されます。


1 少なくとも、これはCPythonに当てはまります。ここでのオブジェクトIDは、オブジェクトが同じメモリアドレスで検出されることを意味します。 リストのメソッドを含むPyObject_RichCompareBool これは、潜在的に複雑なオブジェクト比較の前にオブジェクトポインタをすばやく比較します。その他Python実装は異なる場合があります。

29
Alex Riley

言及する価値があることの1つは、numpy配列が期待どおりに動作することです。

a = np.array((np.nan,))
a[0] in a
# False

テーマのバリエーション:

[np.nan]==[np.nan]
# True
[float('nan')]==[float('nan')]
# False
{np.nan: 0}[np.nan]
# 0
{float('nan'): 0}[float('nan')]
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# KeyError: nan

他のすべては、@ AlexRileyの優れた回答で説明されています。

5
Paul Panzer