2015-02-01 5 views
5

Tracing ein ValueError: cannot convert float NaN to integer zurück fand ich heraus, dass die Zeile:Warum gibt Python Max ('a', 5) den Zeichenfolgenwert zurück?

max('a', 5) 
max(5, 'a') 

a statt 5.

Im obigen Fall zurückkehren ich das Beispiel String a verwendet, aber in meinem konkreten Fall ist die Zeichenfolge ein NaN (das Ergebnis eines Anpassungsprozesses, der nicht konvergierte).

Was ist der Grund für dieses Verhalten? Warum erkennt Python nicht automatisch, dass dort eine Zeichenkette ist und dass sie die Zahl zurückgeben soll?

Noch neugierig ist, dass min()tut wie erwartet seit:

min('a', 5) 
min(5, 'a') 

kehrt 5.

+2

Ähnliche: [Warum ist keiner der kleinste in Python?] (Http: // stackoverflow.com/q/22040724) –

+1

möglich duplicate von [Wie vergleicht Python Zeichenfolge und int?] (http://stackoverflow.com/questions/3270680/how-does-python-compare-string-and-int) – lightandlight

Antwort

11

In Python 2, numerische Werte immer sortieren, bevor Strings und fast alle anderen Typen:

>>> sorted(['a', 5]) 
[5, 'a'] 

Zahlen dann werden kleiner als Strings betrachtet. Bei Verwendung von max() bedeutet dies, dass die Zeichenfolge über eine Zahl ausgewählt wird.

Dass Zahlen kleiner sind, ist eine willkürliche Implementierung Wahl. Siehe Comparisons documentation:

Die Betreiber <, >, ==, >=, <= und != die Werte von zwei Objekten zu vergleichen. Die Objekte müssen nicht den gleichen Typ haben. Wenn beide Zahlen sind, werden sie in einen gemeinsamen Typ konvertiert. Ansonsten werden Objekte verschiedener Typen immer ungleich verglichen und sind konsistent, aber willkürlich geordnet.

Kühne Betonung meins.

Python 2 hat wirklich versucht, heterogene Typen sortierbar zu machen, was viele Probleme verursacht hat, die schwer zu debuggen sind, wie Programmierer, die Integer mit Strings vergleichen und unerwartete Ergebnisse erhalten. Python 3 hat diesen Fehler korrigiert; Sie werden ein TypeError stattdessen erhalten:

>>> max(5, 'a') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: unorderable types: str() > int() 

Ich habe written elsewhere about the ordering rules und sogar re-implemented the Python 2 rules for Python 3, wenn Sie wirklich jene zurück wollte.

+0

I ' M nicht der Downvoter, aber es ist ** nicht ** wahr, dass "numerische Werte immer vor anderen Typen sortieren" - versuche zB "sortiert" (None, 23)) und du wirst oft die 'None' zuerst sehen Es ist kein numerischer Typ. Es ** ist **, oder besser ** war **, wenn Py2 Geschichte ist, eine wirklich willkürliche Entscheidung –

+0

@AlexMartelli: Keine ist die einzige Ausnahme; Ich wollte jedoch nicht die ganzen Regeln aufstellen. Ich verlinke auf eine Antwort, bei der ich in die Tiefe gegangen bin. Die Entscheidungen waren einmal willkürlich, aber da sie sich seither nicht geändert haben, sind sie jetzt eher in Stein gemeißelt. :-) –

+1

@AlexMartelli: berichtigte die schlechte Formulierung im Eröffnungssatz. –

2

In CPython 2.x Strings sind immer größer als Zahlen, deshalb sehen Sie diese Verhaltensweisen.

OTOH, ich verstehe nicht, warum Sie denken, dass 5 "offensichtlich" größer als "a" ist ... Werte verschiedener Typen sind nur aus praktischen Gründen vergleichbar (zB wenn Sie einen RB-Baum mit heterogenen Schlüsseln bauen möchte, dass alles vergleichbar ist), und solche Vergleiche definieren eine strenge schwache Ordnung, aber Vergleiche zwischen Typen sind in keiner Weise sinnvoll (wie vergleicht man eine Zahl mit einer Zeichenkette oder einem Objekt?), nur kohärent.