Ada masalah lain yang tidak ditunjukkan dalam jawaban yang ada. Python diizinkan untuk menggabungkan dua nilai yang tidak dapat diubah, dan nilai int kecil yang dibuat sebelumnya bukan satu-satunya cara hal ini bisa terjadi. Implementasi Python tidak pernah dijamin untuk melakukan ini, tetapi mereka semua melakukannya untuk lebih dari sekedar int kecil.
Untuk satu hal, ada beberapa nilai pra-dibuat lainnya, seperti string kosong tuple
,, str
dan bytes
, dan beberapa string pendek (dalam CPython 3.6, ini adalah 256 karakter Latin-1 string tunggal). Sebagai contoh:
>>> a = ()
>>> b = ()
>>> a is b
True
Tetapi juga, bahkan nilai-nilai yang tidak dibuat sebelumnya bisa identik. Pertimbangkan contoh-contoh ini:
>>> c = 257
>>> d = 257
>>> c is d
False
>>> e, f = 258, 258
>>> e is f
True
Dan ini tidak terbatas pada int
nilai:
>>> g, h = 42.23e100, 42.23e100
>>> g is h
True
Jelas, CPython tidak datang dengan float
nilai yang dibuat sebelumnya untuk 42.23e100
. Jadi, apa yang terjadi di sini?
The CPython compiler akan menggabungkan nilai-nilai konstan beberapa jenis dikenal-berubah seperti int
, float
, str
, bytes
, di unit kompilasi yang sama. Untuk modul, seluruh modul adalah unit kompilasi, tetapi pada penerjemah interaktif, setiap pernyataan adalah unit kompilasi yang terpisah. Karena c
dan d
didefinisikan dalam pernyataan terpisah, nilainya tidak digabungkan. Karena e
dan f
didefinisikan dalam pernyataan yang sama, nilainya digabungkan.
Anda dapat melihat apa yang terjadi dengan membongkar bytecode. Cobalah mendefinisikan fungsi yang berfungsi e, f = 128, 128
dan memanggilnya dis.dis
, dan Anda akan melihat bahwa ada nilai konstan tunggal(128, 128)
>>> def f(): i, j = 258, 258
>>> dis.dis(f)
1 0 LOAD_CONST 2 ((128, 128))
2 UNPACK_SEQUENCE 2
4 STORE_FAST 0 (i)
6 STORE_FAST 1 (j)
8 LOAD_CONST 0 (None)
10 RETURN_VALUE
>>> f.__code__.co_consts
(None, 128, (128, 128))
>>> id(f.__code__.co_consts[1], f.__code__.co_consts[2][0], f.__code__.co_consts[2][1])
4305296480, 4305296480, 4305296480
Anda mungkin memperhatikan bahwa kompiler telah disimpan 128
sebagai konstanta walaupun sebenarnya tidak digunakan oleh bytecode, yang memberi Anda gambaran tentang seberapa sedikit optimasi yang dilakukan kompiler CPython. Yang berarti bahwa tupel (non-kosong) sebenarnya tidak berakhir digabungkan:
>>> k, l = (1, 2), (1, 2)
>>> k is l
False
Menempatkan bahwa dalam fungsi, dis
itu, dan lihat di co_consts
-ada 1
dan 2
, dua (1, 2)
tupel yang berbagi sama 1
dan 2
tetapi tidak identik, dan ((1, 2), (1, 2))
tuple yang memiliki dua tupel yang sama yang berbeda.
Ada satu lagi optimasi yang dilakukan CPython: string interning. Tidak seperti kompilasi pelipatan konstan, ini tidak terbatas pada literal kode sumber:
>>> m = 'abc'
>>> n = 'abc'
>>> m is n
True
Di sisi lain, terbatas pada str
jenisnya, dan untuk tipe penyimpanan internal "ascii compact", "compact", atau "legacy ready" , dan dalam banyak kasus hanya "ascii compact" yang akan diinternir.
Bagaimanapun, aturan untuk nilai apa yang harus, mungkin, atau tidak dapat berbeda bervariasi dari implementasi ke implementasi, dan antara versi dari implementasi yang sama, dan mungkin bahkan antara menjalankan kode yang sama pada salinan yang sama dari implementasi yang sama .
Ini bisa bernilai belajar aturan untuk satu Python tertentu untuk bersenang-senang. Tetapi tidak layak mengandalkan mereka dalam kode Anda. Satu-satunya aturan aman adalah:
- Jangan menulis kode yang mengasumsikan dua nilai tidak berubah yang sama tetapi dibuat secara terpisah adalah identik (jangan gunakan
x is y
, gunakanx == y
)
- Jangan menulis kode yang mengasumsikan dua nilai tidak berubah sama tetapi dibuat secara terpisah adalah berbeda (jangan gunakan
x is not y
, gunakan x != y
)
Atau, dengan kata lain, hanya digunakan is
untuk menguji lajang terdokumentasi (seperti None
) atau yang hanya dibuat di satu tempat dalam kode (seperti _sentinel = object()
idiom).