Saya Google-fu telah gagal saya.
Dalam Python, apakah dua tes berikut untuk kesetaraan setara?
n = 5
# Test one.
if n == 5:
print 'Yay!'
# Test two.
if n is 5:
print 'Yay!'
Apakah ini berlaku untuk objek di mana Anda akan membandingkan instance ( list
katakanlah)?
Oke, jadi ini menjawab pertanyaan saya:
L = []
L.append(1)
if L == [1]:
print 'Yay!'
# Holds true, but...
if L is [1]:
print 'Yay!'
# Doesn't.
Jadi ==
nilai tes mana is
tes untuk melihat apakah mereka adalah objek yang sama?
echo 'import sys;tt=sys.argv[1];print(tt is "foo", tt == "foo", id(tt)==id("foo"))'| python3 - foo
keluaran:False True False
.b = a[:]
bagian salinan daftar operator slice, jadi saya telah mengedit jawaban Anda untuk memiliki komentar di sana. Sepertinya saya baru saja mencapai ambang batas untuk tidak perlu mengedit ulasan saya sebelum diterapkan, jadi mudah-mudahan itu keren dengan Anda. Terlepas dari itu, berikut ini adalah referensi yang berguna untuk cara menyalin daftar yang saya temui dan harus referensi untuk mencari tahu apa yang Anda lakukan: stackoverflow.com/a/2612815/4561887==
. Jadi5.0
misalnya, adalah nilai floating point, sedangkan5
bilangan bulat. Tetapi5.0 == 5
akan tetap kembaliTrue
karena mereka mewakili nilai yang sama. Dalam hal kinerja dan bebek-mengetik,is
selalu diuji oleh juru bahasa dengan membandingkan memori adress operan, sementara dengan==
itu terserah objek untuk memutuskan apakah itu mendefinisikan dirinya sama dengan sesuatu yang lain.1000 is 10**3
mengevaluasi ke True dalam Python 3.7 karena 10 ** 3 adalah tipeint
. Tetapi1000 is 1e3
dievaluasi menjadi False karena 1e3 adalah tipefloat
.1000 is 10**3
bergantung pada implementasi, dan tergantung pada kompiler yang mengevaluasi ekspresi sebelumnya10**3
.x=10; 1000 is x**3
mengevaluasi keFalse
.Ada aturan praktis sederhana untuk memberi tahu Anda kapan harus menggunakan
==
atauis
.==
adalah untuk kesetaraan nilai . Gunakan ketika Anda ingin tahu apakah dua objek memiliki nilai yang sama.is
adalah untuk referensi kesetaraan . Gunakan ketika Anda ingin tahu apakah dua referensi merujuk ke objek yang sama.Secara umum, ketika Anda membandingkan sesuatu dengan tipe sederhana, Anda biasanya memeriksa kesetaraan nilai , jadi Anda harus menggunakannya
==
. Sebagai contoh, maksud dari contoh Anda mungkin untuk memeriksa apakah x memiliki nilai sama dengan 2 (==
), bukan apakahx
secara harfiah merujuk ke objek yang sama dengan 2.Hal lain yang perlu diperhatikan: karena cara kerja implementasi referensi CPython, Anda akan mendapatkan hasil yang tidak terduga dan tidak konsisten jika Anda keliru menggunakan
is
untuk membandingkan persamaan referensi pada bilangan bulat:Itulah yang kami harapkan:
a
danb
memiliki nilai yang sama, tetapi merupakan entitas yang berbeda. Tapi bagaimana dengan ini?Ini tidak konsisten dengan hasil sebelumnya. Apa yang terjadi di sini? Ternyata implementasi referensi objek integer cache Python dalam kisaran -5..256 sebagai contoh tunggal untuk alasan kinerja. Berikut ini contoh yang menunjukkan ini:
Ini adalah alasan lain yang jelas untuk tidak digunakan
is
: perilaku dibiarkan implementasi ketika Anda salah menggunakannya untuk kesetaraan nilai.sumber
a=500
danb=500
, hanya ingin menunjukkan bahwa jika Anda mengatura
danb
ke interger antara [-5, 256],a is b
sebenarnya kembaliTrue
. Informasi lebih lanjut di sini: stackoverflow.com/q/306313/7571052==
menentukan apakah nilainya sama, sementarais
menentukan apakah mereka adalah objek yang sama persis.sumber
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 :is
: periksa identitas - semantik adalah bahwa objek (seperti yang tersimpan dalam memori) adalah objek. Sekali lagi, dokumentasi mengatakan :Dengan demikian, pemeriksaan untuk identitas sama dengan memeriksa kesetaraan ID objek. Itu adalah,
sama dengan:
di mana
id
fungsi builtin yang mengembalikan bilangan bulat yang "dijamin unik di antara objek yang ada secara bersamaan" (lihathelp(id)
) dan di manaa
danb
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
Kasus penggunaan biasa untuk
==
meliputi:Kasus penggunaan umum, sekali lagi, untuk
==
, adalah objek yang ingin mungkin tidak sama objek, melainkan bisa menjadi setara satuArah PEP 8
PEP 8, panduan gaya Python resmi untuk perpustakaan standar juga menyebutkan dua kasus penggunaan untuk
is
: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 ,dan untuk kepentingan konsistensi, merekomendasikan:
Kita dapat melihat bahwa ini adalah perilaku default untuk objek kustom:
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: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
: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.
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.sumber
is None
menjadi perkecualian, tetapi kata itu== None
juga berhasil ...is
untuk membandingkanEnum
s.Apa perbedaan antara
is
dan==
?==
danis
perbandingannya berbeda! Seperti yang sudah dikatakan orang lain:==
membandingkan nilai-nilai objek.is
membandingkan referensi objek.Dalam nama Python merujuk ke objek, misalnya dalam kasus ini
value1
danvalue2
merujuk ke sebuahint
instance yang menyimpan nilai1000
:Karena
value2
mengacu pada objek yang samais
dan==
akan memberiTrue
:Dalam contoh berikut ini, nama
value1
danvalue2
rujuk ke berbagaiint
instance, meskipun keduanya menyimpan bilangan bulat yang sama:Karena nilai yang sama (integer) disimpan
==
akan menjadiTrue
, itu sebabnya sering disebut "perbandingan nilai". Namunis
akan kembaliFalse
karena ini adalah objek yang berbeda:Kapan menggunakan yang mana?
Secara umum
is
perbandingannya jauh lebih cepat. Itu sebabnya cache CPython (atau mungkin menggunakan kembali akan menjadi istilah yang lebih baik) objek-objek tertentu seperti integer kecil, beberapa string, dll. Tetapi ini harus diperlakukan sebagai detail implementasi yang dapat (bahkan jika tidak mungkin) berubah pada titik mana saja tanpa peringatan.Anda hanya
is
boleh menggunakan jika Anda:ingin membandingkan nilai ke konstanta Python . Konstanta dalam Python adalah:
None
True
1False
1NotImplemented
Ellipsis
__debug__
int is int
atauint is float
)np.ma.masked
dari modul NumPy)Dalam setiap kasus lain, Anda harus menggunakan
==
untuk memeriksa kesetaraan.Bisakah saya menyesuaikan perilaku?
Ada beberapa aspek
==
yang belum disebutkan di jawaban lain: Ini bagian dari Python "Model data" . Itu berarti perilakunya dapat dikustomisasi menggunakan__eq__
metode ini. Sebagai contoh:Ini hanya contoh buatan untuk menggambarkan bahwa metode ini benar-benar disebut:
Perhatikan bahwa secara default (jika tidak ada implementasi lain dari
__eq__
dapat ditemukan di kelas atau kacamata super)__eq__
menggunakanis
:Jadi, sebenarnya penting untuk diterapkan
__eq__
jika Anda ingin "lebih" dari sekadar perbandingan referensi untuk kelas khusus!Di sisi lain Anda tidak dapat menyesuaikan
is
cek. Itu akan selalu membandingkan hanya jika Anda memiliki referensi yang sama.Apakah perbandingan ini selalu menghasilkan boolean?
Karena
__eq__
dapat diimplementasikan kembali atau diganti, itu tidak terbatas untuk mengembalikanTrue
atauFalse
. Itu bisa mengembalikan apa saja (tetapi dalam kebanyakan kasus itu harus mengembalikan boolean!)Misalnya dengan array NumPy
==
akan mengembalikan array:Tetapi
is
cek akan selalu kembaliTrue
atauFalse
!1 Seperti yang Aaron Hall katakan dalam komentar:
Umumnya Anda tidak boleh melakukan apa pun
is True
atauis False
memeriksa karena orang biasanya menggunakan "pemeriksaan" ini dalam konteks yang secara implisit mengubah kondisi menjadi boolean (misalnya dalam sebuahif
pernyataan). Jadi melakukanis True
perbandingan dan pemeran boolean implisit adalah melakukan lebih banyak pekerjaan daripada hanya melakukan pemeran boolean - dan Anda membatasi diri Anda untuk boolean (yang tidak dianggap pythonic).Seperti PEP8 menyebutkan:
sumber
is
- nama yang mengarah ke boolean harus diperiksa dengan konteks boolean - sepertiif __debug__:
atauif not __debug__:
. Anda tidak boleh melakukanif __debug__ is True:
atauif __debug__ == True:
- lebih jauh, konstanta hanyalah nilai semantik konstan, bukan singleton, oleh karena itu memeriksais
dalam kasus itu tidak benar secara semantik. Saya menantang Anda untuk menemukan sumber untuk mendukung pernyataan Anda - saya tidak berpikir Anda akan menemukannya.None
,True
,False
dan__debug__
adalah apa yang Anda sebut "nilai semantik konstan", karena mereka tidak dapat dipindahkan. Tapi semuanya adalah lajang.is True
atauif False
memeriksa (tapi ya, ini cukup langka - tetapi jika Anda melakukannya, Anda dapat melakukannya dengan menggunakanis
). Itu sebabnya bahkan CPython kadang-kadang menggunakannya (misalnya di sini atau di sini )Mereka sangat berbeda .
is
memeriksa identitas objek, sementara==
memeriksa kesetaraan (gagasan yang tergantung pada jenis kedua operan).Hanya kebetulan kebetulan bahwa "
is
" tampaknya berfungsi dengan benar dengan bilangan bulat kecil (mis. 5 == 4 +1). Itu karena CPython mengoptimalkan penyimpanan bilangan bulat dalam kisaran (-5 hingga 256) dengan membuatnya menjadi lajang . Perilaku ini sepenuhnya tergantung pada implementasi dan tidak dijamin akan dipertahankan dengan segala macam operasi transformatif minor.Sebagai contoh, Python 3.5 juga membuat singleton string pendek, tetapi mengirisnya mengganggu perilaku ini:
sumber
https://docs.python.org/library/stdtypes.html#comparisons
is
tes untuk identitas==
untuk kesetaraanSetiap nilai integer (kecil) dipetakan ke nilai tunggal, sehingga setiap 3 identik dan sama. Ini adalah detail implementasi, bukan bagian dari spesifikasi bahasa
sumber
Jawaban Anda benar. The
is
Operator membandingkan identitas dua benda. The==
Operator membandingkan nilai-nilai dua benda.Identitas objek tidak pernah berubah begitu telah dibuat; Anda mungkin menganggapnya sebagai alamat objek dalam memori.
Anda dapat mengontrol perilaku perbandingan nilai objek dengan mendefinisikan
__cmp__
metode atau metode perbandingan kaya seperti__eq__
.sumber
Lihatlah pertanyaan Stack Overflow operator “is” Python berperilaku tak terduga dengan bilangan bulat .
Sebagian besar intinya adalah bahwa "
is
" memeriksa untuk melihat apakah mereka adalah objek yang sama, tidak hanya sama satu sama lain (angka di bawah 256 adalah kasus khusus).sumber
Singkatnya,
is
periksa apakah dua referensi menunjuk ke objek yang sama atau tidak.==
memeriksa apakah dua objek memiliki nilai yang sama atau tidak.sumber
Seperti yang dikatakan John Feminella, sebagian besar waktu Anda akan menggunakan == dan! = Karena tujuan Anda adalah membandingkan nilai. Saya hanya ingin mengkategorikan apa yang akan Anda lakukan sepanjang waktu:
Ada satu dan hanya satu contoh dari NoneType yaitu Tidak ada yang tunggal. Konsekuensinya
foo == None
danfoo is None
artinya sama. Namunis
tes lebih cepat dan konvensi Pythonic akan digunakanfoo is None
.Jika Anda melakukan introspeksi atau mengoceh tentang pengumpulan sampah atau memeriksa apakah gadget pemagangan string yang dibuat khusus Anda berfungsi atau semacamnya, maka Anda mungkin memiliki case-use-
foo
nyabar
.Benar dan Salah juga (sekarang) lajang, tetapi tidak ada kasus penggunaan untuk
foo == True
dan tidak ada kasus penggunaan untukfoo is True
.sumber
Sebagian besar dari mereka sudah menjawab to the point. Sama seperti catatan tambahan (berdasarkan pemahaman dan percobaan saya tetapi tidak dari sumber yang didokumentasikan), pernyataan itu
dari jawaban di atas harus dibaca sebagai
. Saya sampai pada kesimpulan ini berdasarkan tes di bawah ini:
Di sini isi daftar dan tupel sama tetapi jenis / kelasnya berbeda.
sumber
Perbedaan python antara is dan equals (==)
Berikut adalah contoh untuk menunjukkan kesamaan dan perbedaannya.
sumber
Ketika orang lain dalam posting ini menjawab pertanyaan secara terperinci, saya akan menekankan terutama perbandingan antara
is
dan==
untuk string yang dapat memberikan hasil yang berbeda dan saya akan mendesak programmer untuk hati-hati menggunakannya.Untuk perbandingan string, pastikan untuk menggunakan
==
daripadais
:Di luar:
Tetapi dalam contoh di bawah ini
==
danis
akan mendapatkan hasil yang berbeda:Di luar:
Kesimpulan:
Gunakan
is
dengan hati-hati untuk membandingkan antara stringsumber