私は、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
_をどのように処理しますか?
アイテムがリストにあるかどうかを確認するには、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実装は異なる場合があります。
言及する価値があることの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の優れた回答で説明されています。