51 votes

Python : les fonctions intégrées max/min dépendent de l'ordre des paramètres

max(float('nan'), 1) évalue à nan

max(1, float('nan')) évalue à 1

Est-ce le comportement souhaité ?


Merci pour les réponses.

max lève une exception lorsque l'itérable est vide. Pourquoi la méthode de Python max soulève une exception lorsque nan est présent ? Ou au moins faire quelque chose d'utile, comme retourner nan ou ignorer nan . Le comportement actuel est très peu sûr et semble complètement déraisonnable.

J'ai trouvé une conséquence encore plus surprenante de ce comportement, je viens donc de poster une Question connexe .

43voto

unutbu Points 222216
In [19]: 1>float('nan')
Out[19]: False

In [20]: float('nan')>1
Out[20]: False

Le flotteur nan n'est ni plus grand ni plus petit que l'entier 1 . max commence par choisir le premier élément, et ne le remplace que lorsqu'il trouve un élément strictement plus grand.

In [31]: max(1,float('nan'))
Out[31]: 1

Depuis nan n'est pas supérieur à 1, 1 est renvoyé.

In [32]: max(float('nan'),1)
Out[32]: nan

Puisque 1 n'est pas plus grand que nan , nan est renvoyé.


PS. Notez que np.max traite float('nan') différemment :

In [36]: import numpy as np
In [91]: np.max([1,float('nan')])
Out[91]: nan

In [92]: np.max([float('nan'),1])
Out[92]: nan

mais si vous souhaitez ignorer np.nan vous pouvez utiliser np.nanmax :

In [93]: np.nanmax([1,float('nan')])
Out[93]: 1.0

In [94]: np.nanmax([float('nan'),1])
Out[94]: 1.0

8voto

katrielalex Points 40655

Je n'avais jamais vu ça avant, mais ça a du sens. Remarquez que nan est un objet très bizarre :

>>> x = float('nan')
>>> x == x
False
>>> x > 1
False
>>> x < 1
False

Je dirais que le comportement de max est indéfini dans ce cas - quelle réponse attendez-vous ? Le seul comportement raisonnable est de supposer que les opérations sont antisymétriques.


Remarquez que vous pouvez reproduire ce comportement en créant une classe cassée :

>>> class Broken(object):
...     __le__ = __ge__ = __eq__ = __lt__ = __gt__ = __ne__ =
...     lambda self, other: False
...
>>> x = Broken()
>>> x == x
False
>>> x < 1
False
>>> x > 1
False
>>> max(x, 1)
<__main__.Broken object at 0x024B5B50>
>>> max(1, x)
1

1voto

terminus Points 3966

Max fonctionne de la manière suivante :

Le premier élément est défini comme maxval, puis le suivant est comparé à cette valeur. La comparaison retournera toujours False :

>>> float('nan') < 1
False
>>> float('nan') > 1
False

Ainsi, si la première valeur est nan, alors (puisque la comparaison renvoie false) elle ne sera pas remplacée à l'étape suivante.

Par contre, si 1 est le premier, la même chose se produit : mais dans ce cas, puisque 1 a été fixé, il sera le maximum.

Vous pouvez vérifier cela dans le code python, il suffit de regarder la fonction min_max dans Python/bltinmodule.c

0voto

Ante Points 2193

Description du comportement nan PEP 754

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X