Bagaimana Python 2 membandingkan string dan int? Mengapa daftar membandingkan lebih besar daripada angka, dan tupel lebih besar dari daftar?

178

Cuplikan berikut ini dijelaskan dengan output ( seperti yang terlihat di ideone.com ):

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

Adakah yang bisa menjelaskan mengapa outputnya seperti itu?


Detail implementasi

  • Apakah perilaku ini diamanatkan oleh spesifikasi bahasa, atau hanya untuk implementator?
  • Apakah ada perbedaan antara implementasi Python utama?
  • Apakah ada perbedaan antara versi bahasa Python?
polygenelubricants
sumber
23
Dari 3000 dups pertanyaan ini, yang ini memiliki jawaban yang menjelaskan mengapa bahasa dirancang dengan cara ini (dan mengapa itu dirancang ulang dalam 3.x). Itu bukan bagian dari pertanyaan ini, tetapi merupakan bagian dari banyak pertanyaan yang terhubung di sini.
abarnert

Jawaban:

209

Dari manual python 2 :

Detail implementasi CPython: Objek dengan tipe yang berbeda kecuali angka diurutkan berdasarkan nama tipenya; objek dari jenis yang sama yang tidak mendukung perbandingan yang tepat dipesan oleh alamatnya.

Ketika Anda memesan dua string atau dua jenis numerik, pemesanan dilakukan dengan cara yang diharapkan (pemesanan leksikografis untuk string, pemesanan numerik untuk bilangan bulat).

Saat Anda memesan tipe numerik dan non-numerik, tipe numerik yang lebih dulu.

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

Saat Anda memesan dua jenis yang tidak kompatibel di mana tidak ada angka, mereka dipesan berdasarkan urutan abjad dari nama pengetik mereka:

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

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

Satu pengecualian adalah kelas gaya lama yang selalu datang sebelum kelas gaya baru.

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

Apakah perilaku ini diamanatkan oleh spesifikasi bahasa, atau hanya untuk implementator?

Tidak ada spesifikasi bahasa . The referensi bahasa mengatakan:

Kalau tidak, objek dari tipe yang berbeda selalu membandingkan tidak sama, dan dipesan secara konsisten tetapi sewenang-wenang.

Jadi ini adalah detail implementasi.

Apakah ada perbedaan antara implementasi Python utama?

Saya tidak bisa menjawab yang ini karena saya hanya menggunakan implementasi CPython resmi, tetapi ada implementasi lain dari Python seperti PyPy.

Apakah ada perbedaan antara versi bahasa Python?

Dalam Python 3.x perilaku telah diubah sehingga upaya untuk memesan integer dan string akan memunculkan kesalahan:

>>> '10' > 5
Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
    '10' > 5
TypeError: unorderable types: str() > int()
Mark Byers
sumber
55
Itu bagus bahwa mereka mengubahnya di Py3k. Ketika saya pertama kali melihat pertanyaan ini, pikiran saya adalah 'apa, ini tidak menimbulkan kesalahan?'.
JAL
9
NB Pengecualian terhadap aturan 2.x bahwa tipe yang berbeda diurutkan berdasarkan nama tipe adalah bahwa objek None selalu membandingkan lebih sedikit daripada setiap tipe lainnya. Dalam 3.x membandingkan Tidak Ada dengan tipe lain masih akan meningkatkan TypeError.
Dave Kirby
4
@ KarelBilek: bool adalah tipe numerik. Dan Benar == 1 jadi bukan <juga>.
abarnert
3
Urutan leksografis nama jenisnya? Kapan Anda ingin ini menjadi fitur? Siapa yang akan menggunakannya?
Jack
3
Fun Fakta: complex(1,0) > 'abc'adalah Falsetetapi complex(1,0) > complex(0,0)menimbulkanTypeError
Eric Duminil
24

String yang dibandingkan leksikografis, dan jenis berbeda dibandingkan dengan nama jenis mereka ( "int"< "string"). 3.x memperbaiki poin kedua dengan membuatnya tidak dapat dibandingkan.

Ignacio Vazquez-Abrams
sumber
3
Tetapi dalam python2 int kurang dari dicts sehingga tidak bisa hanya secara leksikografis berdasarkan nama tipe?
Tony Suffolk 66
Saya baru saja menemukan jawaban ini dan setuju dengan Tony Suffolk. Objek TIDAK dipesan dengan nama tipe ketika berbeda.
Exelian
@ TonySuffolk66 tipe numerik adalah pengecualian dari aturan itu. NumericType selalu lebih rendah dari tipe lainnya (kecuali NoneType) di 2.7.
tinggalkan