Pertanyaan Mengapa membandingkan string dengan Python menggunakan '==' atau 'is' terkadang menghasilkan hasil yang berbeda?


Saya punya program Python di mana dua variabel ditetapkan ke nilai 'public'. Dalam ekspresi kondisional, saya memiliki perbandingan var1 is var2 yang gagal, tetapi jika saya mengubahnya var1 == var2 itu kembali True.

Sekarang jika saya membuka interpreter Python saya dan melakukan perbandingan "adalah" yang sama, itu berhasil.

>>> s1 = 'public'
>>> s2 = 'public'
>>> s2 is s1
True

Apa yang kulewatkan di sini?


891
2017-10-01 15:40


asal


Jawaban:


is adalah pengujian identitas, == adalah pengujian kesetaraan. apa yang terjadi dalam kode Anda akan diemulasikan di interpreter seperti ini:

>>> a = 'pub'
>>> b = ''.join(['p', 'u', 'b'])
>>> a == b
True
>>> a is b
False

jadi, tidak heran mereka tidak sama, kan?

Dengan kata lain: is adalah id(a) == id(b)


1230
2017-10-01 15:45



Jawaban lain di sini benar: is digunakan untuk identitas perbandingan, sementara == digunakan untuk persamaan perbandingan. Karena apa yang Anda pedulikan adalah kesetaraan (dua string harus mengandung karakter yang sama), dalam hal ini is operator hanya salah dan Anda harus menggunakan == sebagai gantinya.

Alasannya is bekerja secara interaktif adalah (kebanyakan) literal string diinternir secara default. Dari Wikipedia:

String beruntun mempercepat string   perbandingan, yang terkadang a   bottleneck kinerja dalam aplikasi   (seperti kompiler dan dinamis   runtime bahasa pemrograman) itu   sangat bergantung pada tabel hash dengan   kunci string. Tanpa magang,   memeriksa dua string yang berbeda   sama artinya memeriksa setiap   karakter dari kedua string. Ini adalah   lambat karena beberapa alasan: itu   inheren O (n) dalam panjang   string; biasanya membutuhkan bacaan   dari beberapa wilayah memori, yang   mengambil waktu; dan bacaan mengisi   cache prosesor, artinya ada lebih sedikit   cache tersedia untuk kebutuhan lainnya. Dengan   string yang diinternir, sebuah objek sederhana   Tes identitas sudah cukup setelah   operasi magang orisinal; ini adalah   biasanya diimplementasikan sebagai penunjuk   tes kesetaraan, biasanya hanya satu   instruksi mesin tanpa memori   referensi sama sekali.

Jadi, ketika Anda memiliki dua literal string (kata-kata yang secara harfiah diketikkan ke dalam kode sumber program Anda, dikelilingi oleh tanda kutip) dalam program Anda yang memiliki nilai yang sama, kompiler Python akan secara otomatis magang string, membuat keduanya disimpan pada saat yang sama. lokasi memori. (Perhatikan bahwa ini tidak selalu terjadi, dan aturan untuk saat ini terjadi cukup berbelit-belit, jadi tolong jangan bergantung pada perilaku ini dalam kode produksi!)

Karena dalam sesi interaktif Anda kedua string sebenarnya disimpan di lokasi memori yang sama, keduanya memiliki kesamaan identitas, sehingga is operator berfungsi seperti yang diharapkan. Tetapi jika Anda membangun string dengan beberapa metode lain (bahkan jika string tersebut mengandung persis karakter yang sama), maka string mungkin sama, tetapi tidak string yang sama - Artinya, itu berbeda identitas, karena disimpan di tempat yang berbeda di memori.


440
2017-10-01 16:02



Itu iskata kunci adalah tes untuk identitas objek sementara == adalah perbandingan nilai.

Jika Anda menggunakan is, hasilnya akan benar jika dan hanya jika objek adalah objek yang sama. Namun, == akan berlaku setiap saat nilai-nilai objeknya sama.


94
2017-10-01 15:45



Satu hal terakhir yang perlu diperhatikan, Anda dapat menggunakan fungsi magang untuk memastikan bahwa Anda mendapatkan referensi ke string yang sama:

>>> a = intern('a')
>>> a2 = intern('a')
>>> a is a2
True

Seperti yang disebutkan di atas, Anda mungkin tidak perlu melakukan hal itu untuk menentukan persamaan pada string. Tapi ini mungkin berguna untuk mengetahui apakah Anda memiliki beberapa jenis persyaratan aneh untuk digunakan is.

Perhatikan bahwa fungsi magang dipindahkan dari fungsi yang sedang dibangun menjadi berada di modul sys untuk Python 3.


48
2017-10-01 16:04



is adalah pengujian identitas, == adalah pengujian kesetaraan. Apa ini artinya itu is adalah cara untuk memeriksa apakah ada dua hal sama hal-hal, atau hanya setara.

Katakan Anda punya yang sederhana person obyek. Jika diberi nama 'Jack' dan berusia '23' tahun, itu setara dengan Jack berusia 23 tahun, tetapi bukan orang yang sama.

class Person(object):
   def __init__(self, name, age):
       self.name = name
       self.age = age

   def __eq__(self, other):
       return self.name == other.name and self.age == other.age

jack1 = Person('Jack', 23)
jack2 = Person('Jack', 23)

jack1 == jack2 #True
jack1 is jack2 #False

Mereka seumuran, tetapi mereka bukan orang yang sama. String mungkin setara dengan string lain, tetapi itu bukan objek yang sama.


28
2018-04-29 00:56



Ini adalah catatan samping, tetapi dalam python idiomatik, Anda akan sering melihat hal-hal seperti:

if x is None: 
    # some clauses

Ini aman, karena ada dijamin menjadi salah satu contoh dari Obyek Null (yaitu, Tidak ada).


27
2017-10-01 18:51



Jika Anda tidak yakin dengan apa yang Anda lakukan, gunakan '=='. Jika Anda memiliki sedikit lebih banyak pengetahuan tentang hal itu, Anda dapat menggunakan 'is' untuk objek yang dikenal seperti 'Tidak Ada'.

Jika tidak, Anda akan berakhir bertanya-tanya mengapa hal-hal tidak berhasil dan mengapa hal ini terjadi:

>>> a = 1
>>> b = 1
>>> b is a
True
>>> a = 6000
>>> b = 6000
>>> b is a
False

Saya bahkan tidak yakin jika beberapa hal dijamin tetap sama antara versi / implementasi python yang berbeda.


23
2017-10-01 16:57



Dari pengalaman saya yang terbatas dengan python, is digunakan untuk membandingkan dua objek untuk melihat apakah mereka adalah objek yang sama dibandingkan dengan dua objek yang berbeda dengan nilai yang sama. == digunakan untuk menentukan apakah nilai identik.

Ini contoh yang bagus:

>>> s1 = u'public'
>>> s2 = 'public'
>>> s1 is s2
False
>>> s1 == s2
True

s1 adalah string unicode, dan s2 adalah string normal. Mereka bukan tipe yang sama, tetapi memiliki nilai yang sama.


16
2017-10-01 15:48



Saya pikir itu ada hubungannya dengan fakta bahwa, ketika perbandingan 'adalah' mengevaluasi ke salah, dua objek yang berbeda digunakan. Jika mengevaluasi ke benar, itu berarti secara internal itu menggunakan objek yang sama persis dan tidak menciptakan yang baru, mungkin karena Anda membuat mereka dalam pecahan dari 2 atau lebih detik dan karena tidak ada kesenjangan waktu yang besar di antara itu dioptimalkan dan menggunakan objek yang sama.

Inilah mengapa Anda harus menggunakan operator kesetaraan ==tidak is, untuk membandingkan nilai objek string.

>>> s = 'one'
>>> s2 = 'two'
>>> s is s2
False
>>> s2 = s2.replace('two', 'one')
>>> s2
'one'
>>> s2 is s
False
>>> 

Dalam contoh ini, saya membuat s2, yang merupakan objek string yang berbeda yang sebelumnya sama dengan 'satu' tetapi bukan objek yang sama s, karena penerjemah tidak menggunakan objek yang sama karena saya awalnya tidak menugaskannya ke 'satu', jika saya memilikinya akan membuat mereka objek yang sama.


12
2017-10-01 15:45



Saya percaya bahwa ini dikenal sebagai string "diasingkan". Python melakukan ini, begitu juga Java, dan begitu juga C dan C ++ saat mengkompilasi dalam mode yang dioptimalkan.

Jika Anda menggunakan dua string yang identik, alih-alih membuang memori dengan membuat dua objek string, semua string yang diinternet dengan isi yang sama mengarah ke memori yang sama.

Ini menyebabkan operator Python "adalah" mengembalikan True karena dua string dengan isi yang sama menunjuk pada objek string yang sama. Ini juga akan terjadi di Jawa dan di C.

Ini hanya berguna untuk penghematan memori sekalipun. Anda tidak dapat mengandalkannya untuk menguji kesetaraan string, karena berbagai interpreter dan kompiler dan mesin JIT tidak dapat selalu melakukannya.


11
2017-10-01 15:59