Wie vergleicht Python 2 String und Int? Warum werden Listen größer als Zahlen und Tupel größer als Listen verglichen?

178

Das folgende Snippet ist mit der Ausgabe versehen ( wie auf ideone.com zu sehen ):

print "100" < "2"      # True
print "5" > "9"        # False

print "100" < 2        # False
print 100 < "2"        # True

print 5 > "9"          # False
print "5" > 9          # True

print [] > float('inf') # True
print () > []          # True

Kann jemand erklären, warum die Ausgabe als solche ist?


Implementierungsdetails

  • Wird dieses Verhalten von der Sprachspezifikation vorgegeben oder liegt es an den Implementierern?
  • Gibt es Unterschiede zwischen den wichtigsten Python-Implementierungen?
  • Gibt es Unterschiede zwischen Versionen der Python-Sprache?
Polygenschmierstoffe
quelle
23
Von den 3000 Dups dieser Frage hat diese eine Antwort, die erklärt, warum die Sprache auf diese Weise entworfen wurde (und warum sie in 3.x neu gestaltet wurde). Das ist nicht Teil dieser Frage, aber Teil vieler Fragen, die hier verlinkt werden.
abarnert

Antworten:

209

Aus dem Python 2-Handbuch :

CPython-Implementierungsdetail: Objekte unterschiedlicher Typen mit Ausnahme von Nummern werden nach ihren Typnamen sortiert. Objekte desselben Typs, die keinen ordnungsgemäßen Vergleich unterstützen, werden nach ihrer Adresse sortiert.

Wenn Sie zwei Zeichenfolgen oder zwei numerische Typen bestellen, erfolgt die Reihenfolge wie erwartet (lexikografische Reihenfolge für Zeichenfolge, numerische Reihenfolge für Ganzzahlen).

Wenn Sie einen numerischen und einen nicht numerischen Typ bestellen, steht der numerische Typ an erster Stelle.

>>> 5 < 'foo'
True
>>> 5 < (1, 2)
True
>>> 5 < {}
True
>>> 5 < [1, 2]
True

Wenn Sie zwei inkompatible Typen bestellen, bei denen keiner numerisch ist, werden sie nach der alphabetischen Reihenfolge ihrer Typnamen sortiert:

>>> [1, 2] > 'foo'   # 'list' < 'str' 
False
>>> (1, 2) > 'foo'   # 'tuple' > 'str'
True

>>> class Foo(object): pass
>>> class Bar(object): pass
>>> Bar() < Foo()
True

Eine Ausnahme bilden Klassen im alten Stil, die immer vor Klassen im neuen Stil stehen.

>>> class Foo: pass           # old-style
>>> class Bar(object): pass   # new-style
>>> Bar() < Foo()
False

Wird dieses Verhalten von der Sprachspezifikation vorgegeben oder liegt es an den Implementierern?

Es gibt keine Sprachspezifikation . Die Sprachreferenz sagt:

Andernfalls werden Objekte unterschiedlicher Typen immer ungleich verglichen und sind konsistent, aber willkürlich geordnet.

Es ist also ein Implementierungsdetail.

Gibt es Unterschiede zwischen den wichtigsten Python-Implementierungen?

Ich kann diese Frage nicht beantworten, da ich nur die offizielle CPython-Implementierung verwendet habe, aber es gibt andere Implementierungen von Python wie PyPy.

Gibt es Unterschiede zwischen Versionen der Python-Sprache?

In Python 3.x wurde das Verhalten so geändert, dass der Versuch, eine Ganzzahl und eine Zeichenfolge zu bestellen, einen Fehler auslöst:

>>> '10' > 5
Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
    '10' > 5
TypeError: unorderable types: str() > int()
Mark Byers
quelle
55
Gut, dass sie es in Py3k geändert haben. Als ich diese Frage zum ersten Mal sah, waren meine Gedanken: "Was, das wirft keinen Fehler auf?".
JAL
9
Hinweis: Eine Ausnahme von der 2.x-Regel, dass verschiedene Typen nach dem Namen des Typs geordnet sind, besteht darin, dass das Objekt None immer mit weniger als jedem anderen Typ verglichen wird. Wenn Sie in 3.x None mit einem anderen Typ vergleichen, wird weiterhin ein TypeError ausgelöst.
Dave Kirby
4
@KarelBilek: bool ist ein numerischer Typ. Und True == 1, also ist es weder <noch>.
Abarnert
3
Lexographische Reihenfolge ihrer Typnamen? Wann möchten Sie jemals, dass dies eine Funktion ist? Wer würde das jemals benutzen?
Jack
3
Lustige Tatsache: complex(1,0) > 'abc'ist Falseaber complex(1,0) > complex(0,0)erhöht einTypeError
Eric Duminil
24

Zeichenfolgen werden lexikografisch verglichen, und unterschiedliche Typen werden anhand des Namens ihres Typs ( "int"< "string") verglichen . 3.x behebt den zweiten Punkt, indem es sie nicht vergleichbar macht.

Ignacio Vazquez-Abrams
quelle
3
Aber in python2 sind int's weniger als dicts, also kann es nicht nur lexikographisch nach Typname sein?
Tony Suffolk 66
Ich bin gerade auf diese Antwort gestoßen und stimme Tony Suffolk zu. Objekte werden NICHT nach dem Typnamen sortiert, wenn sie unterschiedlich sind.
Exelian
@ TonySuffolk66 Der numerische Typ ist eine Ausnahme von dieser Regel. NumericType ist in 2.7 immer niedriger als jeder andere Typ (außer NoneType).
Lef