Apakah ada perbedaan antara ==
dan is
dalam Python?
Ya, mereka memiliki perbedaan yang sangat penting.
==
: periksa untuk kesetaraan - semantik adalah bahwa objek yang setara (yang tidak harus objek yang sama) akan diuji sama. Seperti yang dikatakan dalam dokumentasi :
Operator <,>, ==,> =, <=, dan! = Membandingkan nilai dari dua objek.
is
: periksa identitas - semantik adalah bahwa objek (seperti yang tersimpan dalam memori) adalah objek. Sekali lagi, dokumentasi mengatakan :
Operator is
dan is not
uji untuk identitas objek: x is y
benar jika dan hanya jika x
dan y
adalah objek yang sama. Identitas objek ditentukan menggunakan id()
fungsi. x is not y
menghasilkan nilai kebenaran terbalik.
Dengan demikian, pemeriksaan untuk identitas sama dengan memeriksa kesetaraan ID objek. Itu adalah,
a is b
sama dengan:
id(a) == id(b)
di mana id
fungsi builtin yang mengembalikan bilangan bulat yang "dijamin unik di antara objek yang ada secara bersamaan" (lihat help(id)
) dan di mana a
dan b
merupakan objek arbitrer.
Petunjuk Penggunaan Lainnya
Anda harus menggunakan perbandingan ini untuk semantiknya. Gunakan is
untuk memeriksa identitas dan ==
untuk memeriksa kesetaraan.
Jadi secara umum, kami gunakan is
untuk memeriksa identitas. Ini biasanya berguna ketika kita memeriksa objek yang seharusnya hanya ada satu kali di memori, disebut sebagai "singleton" dalam dokumentasi.
Gunakan kasing untuk is
memasukkan:
None
- nilai enum (saat menggunakan Enums dari modul enum)
- biasanya modul
- biasanya objek kelas dihasilkan dari definisi kelas
- biasanya benda fungsi dihasilkan dari definisi fungsi
- hal lain yang seharusnya hanya ada satu kali dalam memori (semua lajang, umumnya
- objek spesifik yang Anda inginkan dengan identitas
Kasus penggunaan biasa untuk ==
meliputi:
- angka, termasuk bilangan bulat
- string
- daftar
- set
- kamus
- objek yang bisa diubahsuaikan
- objek kekal bawaan lainnya, dalam banyak kasus
Kasus penggunaan umum, sekali lagi, untuk ==
, adalah objek yang ingin mungkin tidak sama objek, melainkan bisa menjadi setara satu
Arah PEP 8
PEP 8, panduan gaya Python resmi untuk perpustakaan standar juga menyebutkan dua kasus penggunaan untukis
:
Perbandingan dengan orang lajang seperti None
harus selalu dilakukan dengan is
atau
is not
, tidak pernah dengan operator kesetaraan.
Juga, berhati-hatilah menulis if x
ketika Anda benar-benar bermaksud if x is not None
- misalnya ketika menguji apakah suatu variabel atau argumen yang defaultnya None
diatur ke beberapa nilai lain. Nilai lainnya mungkin memiliki tipe (seperti wadah) yang bisa salah dalam konteks boolean!
Menyimpulkan kesetaraan dari identitas
Jika is
benar, kesetaraan biasanya dapat disimpulkan - secara logis, jika suatu objek itu sendiri, maka ia harus diuji sebagai setara dengan dirinya sendiri.
Dalam banyak kasus, logika ini benar, tetapi ia bergantung pada implementasi __eq__
metode khusus. Seperti yang dikatakan para dokter ,
Perilaku default untuk perbandingan kesetaraan ( ==
dan !=
) didasarkan pada identitas objek. Oleh karena itu, perbandingan kesetaraan contoh dengan identitas yang sama menghasilkan persamaan, dan perbandingan persamaan contoh dengan identitas berbeda menghasilkan ketidaksetaraan. Motivasi untuk perilaku default ini adalah keinginan bahwa semua objek harus refleksif (yaitu x adalah y menyiratkan x == y).
dan untuk kepentingan konsistensi, merekomendasikan:
Perbandingan kesetaraan harus bersifat refleksif. Dengan kata lain, objek identik harus sama dengan:
x is y
tersirat x == y
Kita dapat melihat bahwa ini adalah perilaku default untuk objek kustom:
>>> class Object(object): pass
>>> obj = Object()
>>> obj2 = Object()
>>> obj == obj, obj is obj
(True, True)
>>> obj == obj2, obj is obj2
(False, False)
Kontrapositif juga biasanya benar - jika sesuatu diuji tidak sama, Anda biasanya dapat menyimpulkan bahwa mereka bukan objek yang sama.
Karena tes untuk kesetaraan dapat disesuaikan, kesimpulan ini tidak selalu berlaku untuk semua jenis.
Pengecualian
Pengecualian yang penting adalah nan
- selalu diuji sebagai tidak sama dengan dirinya sendiri:
>>> nan = float('nan')
>>> nan
nan
>>> nan is nan
True
>>> nan == nan # !!!!!
False
Memeriksa identitas bisa menjadi pemeriksaan yang jauh lebih cepat daripada memeriksa kesetaraan (yang mungkin membutuhkan memeriksa anggota secara rekursif).
Tapi itu tidak bisa menggantikan kesetaraan di mana Anda dapat menemukan lebih dari satu objek sebagai setara.
Perhatikan bahwa membandingkan persamaan daftar dan tupel akan mengasumsikan bahwa identitas objek sama (karena ini adalah pemeriksaan cepat). Ini dapat membuat kontradiksi jika logikanya tidak konsisten - seperti untuk nan
:
>>> [nan] == [nan]
True
>>> (nan,) == (nan,)
True
Kisah Peringatan:
Pertanyaannya adalah mencoba untuk menggunakan is
untuk membandingkan bilangan bulat. Anda tidak boleh berasumsi bahwa instance dari integer adalah instance yang sama dengan yang diperoleh dengan referensi lain. Kisah ini menjelaskan mengapa.
Seorang komentator memiliki kode yang mengandalkan fakta bahwa bilangan bulat kecil (-5 hingga 256 inklusif) adalah lajang dalam Python, alih-alih memeriksa kesetaraan.
Wow, ini dapat menyebabkan beberapa bug berbahaya. Saya punya beberapa kode yang memeriksa apakah a adalah b, yang berfungsi seperti yang saya inginkan karena a dan b biasanya angka kecil. Bug hanya terjadi hari ini, setelah enam bulan di produksi, karena a dan b akhirnya cukup besar untuk tidak di-cache. - gwg
Ini berhasil dalam pengembangan. Mungkin telah melewati beberapa unittests.
Dan itu berhasil dalam produksi - sampai kode memeriksa bilangan bulat yang lebih besar dari 256, pada saat itu gagal dalam produksi.
Ini adalah kegagalan produksi yang bisa saja tertangkap dalam tinjauan kode atau mungkin dengan pemeriksa gaya.
Biarkan saya tekankan: jangan gunakan is
untuk membandingkan bilangan bulat.
echo 'import sys;tt=sys.argv[1];print(tt is "foo", tt == "foo", id(tt)==id("foo"))'| python3 - foo
keluaran:False True False
.