dans l'opérateur, flotteur ("Nan") et np.Nan

je croyais que l' in l'opérateur en Python vérifie la présence d'un élément dans une collection en utilisant la vérification de l'égalité ==, donc element in some_list est équivalent à any(x == element for x in some_list). Par exemple:

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

ou

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

Toutefois, il est bien connu que NaN n'est pas égal à lui-même. J'ai donc attendu que float("NaN") in [float("NaN")]False. Et c'est False en effet.

cependant, si nous utilisons numpy.nan au lieu de float("NaN"), la situation est assez différents:

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

Mais np.nan == np.nan donne False!

Comment est-ce possible? Quelle est la différence entre np.nan et

2 ответов

pour vérifier si l'élément est dans la liste, Python teste l'identité de l'objet premier, et teste ensuite l'égalité seulement si les objets sont différents.1

float("NaN") in [float("NaN")] est faux parce que deux NaN objets sont impliqués dans la comparaison. Le test d'identité renvoie donc False, et le test d'égalité renvoie aussi False puisque NaN != NaN.

np.nan in [np.nan, 1, 2] cependant est vrai parce que le NaN objet est impliqué dans la comparaison. Le test pour l'identité de l'objet renvoie True et donc Python reconnaît immédiatement l'élément comme étant dans la liste.

__contains__ méthode (invoquée en utilisant in) pour beaucoup d'autres types de conteneur de Python, tels que les tuples et les sets, est implémenté en utilisant la même vérification.


1 au moins c'est vrai à CPython. L'identité de l'objet signifie ici que les objets sont trouvé à la même adresse mémoire:contient la méthode pour les listes est effectuée en utilisant PyObject_RichCompareBool qui compare rapidement les pointeurs d'objet avant une comparaison d'objet potentiellement plus compliquée. D'autres implémentations Python peuvent différer.

27
répondu Alex Riley 2017-12-09 14:05:01
la source

une chose qui mérite d'être mentionnée est que les tableaux de numpy se comportent comme prévu:

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

les Variations du thème:

[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

tout le reste est couvert dans l'excellente réponse de @AlexRiley.

5
répondu Paul Panzer 2017-12-09 00:16:48
la source

Autres questions sur