Apakah False == 0 dan True == 1 detail implementasi atau apakah dijamin oleh bahasa?

244

Apakah itu dijamin False == 0dan True == 1, dengan Python (dengan asumsi bahwa mereka tidak dipindahkan oleh pengguna)? Misalnya, apakah dengan cara apa pun dijamin bahwa kode berikut akan selalu menghasilkan hasil yang sama, apa pun versi Python (baik yang ada dan, kemungkinan, yang akan datang)?

0 == False  # True
1 == True   # True
['zero', 'one'][False]  # is 'zero'

Referensi apa pun ke dokumentasi resmi akan sangat dihargai!

Sunting : Sebagaimana dicatat dalam banyak jawaban, boolmewarisi dari int. Pertanyaan karena itu dapat disusun kembali sebagai: "Apakah dokumentasi secara resmi mengatakan bahwa programmer dapat mengandalkan boolean yang diwarisi dari bilangan bulat, dengan nilai 0dan1 ?". Pertanyaan ini relevan untuk menulis kode yang kuat yang tidak akan gagal karena detail implementasi!

Eric O Lebigot
sumber
63
@ S.Lott: Ada banyak alasan untuk mengajukan pertanyaan di atas. Jadi, ada beberapa contoh di mana mengandalkan booleans menjadi integer membuat kode Anda lebih sederhana: apakah Anda harus mengubahnya? Atau, Anda mungkin melihat tempat dalam kode yang ditulis oleh orang lain yang mengandalkan booleans menjadi bilangan bulat: apakah Anda mengganggu apa yang Anda modifikasi dalam kode untuk "memperbaiki" kode yang ada, atau Anda dapat yakin bahwa pengkodean saat ini adalah suara ? Ada banyak contoh lain. Secara umum, baik untuk mengetahui aturan permainan, sehingga Anda dapat memainkannya dengan baik dan memprogram dengan suara yang baik.
Eric O Lebigot
10
@ S.Lott: Posting asli persisnya menggemakan poin Anda: pertanyaannya pada dasarnya adalah "Apakah ini detail implementasi?", Karena saya sepenuhnya setuju dengan Anda pada gagasan bahwa seseorang tidak boleh bergantung pada detail implementasi. Jika boolean secara resmi bilangan bulat dari nilai yang diketahui, maka kode dalam pertanyaan tidak bergantung pada detail implementasi, yang baik.
Eric O Lebigot
5
@ S. Lot: Mengetahui bahwa False == 0 dan True == 1 membuatnya lebih mudah untuk menghitung berapa banyak bools dalam suatu urutan yang benar: Anda hanya dapat menulis sum(bool_list). Kalau tidak, Anda harus menulis sum(1 for x bool_list if x).
dan04
8
@dan: Itu salah satu cara menghitung boolean. Saya akan mengatakan itu bool_list.count(True)lebih eksplisit; itu juga sekitar 3 kali lebih cepat ... :)
Eric O Lebigot
2
@akonsu Sebagai jawaban menunjukkan, Python boolean yang sebenarnya (subclass tertentu) bilangan bulat. Selanjutnya, Python jelas memiliki tipe; mungkin Anda bermaksud bahwa itu "tidak diketik secara statis"? Juga, saya tidak yakin apa yang Anda maksud dengan "Saya tidak akan membuat kesalahan dalam kode". Sekarang, saya tidak pernah suka mencampur booleans dengan integer, karena mereka secara konsep berbeda, dan saya tidak keberatan jika Python booleans bukan bilangan bulat, tetapi mengetahui bahwa mereka, dengan nilai 0 dan 1, berguna.
Eric O Lebigot

Jawaban:

183

Dalam Python 2.x ini tidak dijamin karena mungkin Truedan Falseakan dipindahkan. Namun, bahkan jika ini terjadi, boolean True dan boolean False masih dikembalikan dengan benar untuk perbandingan.

Dalam Python 3.x Truedan Falsemerupakan kata kunci dan akan selalu sama dengan 1dan 0.

Dalam keadaan normal di Python 2, dan selalu dalam Python 3:

Falseobjek adalah tipe boolyang merupakan subkelas dari int:

object
   |
 int
   |
 bool

Ini adalah satu-satunya alasan mengapa dalam contoh Anda, ['zero', 'one'][False]bekerja. Itu tidak akan bekerja dengan objek yang bukan subkelas integer, karena pengindeksan daftar hanya bekerja dengan integer, atau objek yang mendefinisikan __index__metode (terima kasih mark-dickinson ).

Edit:

Ini berlaku untuk versi python saat ini, dan versi Python 3. Dokumen untuk python 2.6 dan dokumen untuk Python 3 keduanya mengatakan:

Ada dua jenis bilangan bulat: [...] Integer (int) [...] Booleans (bool)

dan di subbagian boolean:

Boolean: Ini mewakili nilai kebenaran Salah dan Benar [...] Nilai Boolean berperilaku seperti nilai 0 dan 1, masing-masing, dalam hampir semua konteks, pengecualian adalah bahwa ketika dikonversi ke string, string "False" atau "True "masing-masing dikembalikan.

Ada juga, untuk Python 2 :

Dalam konteks numerik (misalnya ketika digunakan sebagai argumen ke operator aritmatika), mereka [False dan True] berperilaku seperti bilangan bulat 0 dan 1, masing-masing.

Jadi boolean secara eksplisit dianggap sebagai bilangan bulat dalam Python 2.6 dan 3.

Jadi Anda aman sampai Python 4 datang. ;-)

Olivier Verdier
sumber
2
0 == 0,0 mengembalikan Benar sementara ['nol', 'satu'] [0,0] gagal. ['nol', 'satu'] [Salah] bekerja karena bool adalah subkelas int. (int .__ subclass __ () mengembalikan [<type 'bool'>])
luc
20
Nitpick: objek apa pun yang menyediakan __index__metode dapat digunakan sebagai indeks daftar; bukan hanya subkelas intatau long.
Mark Dickinson
Ah ya, itu ada di sana juga. Tetapi akan lebih baik untuk tidak menautkan ke dokumentasi Python 3.0: 3.0 sudah mati. :)
Mark Dickinson
4
Re: "Dalam Python 2.x ini tidak dijamin karena dimungkinkan untuk Benar dan Salah untuk dipindahkan". IMHO, sementara ini benar, siapa pun yang ditugaskan kembali Benar atau Salah berhak menerima konsekuensi aneh apa pun yang mereka dapatkan. Secara khusus, menyimpan True sebelum penugasan kembali dan kemudian membandingkan hasilnya dengan True setelah penugasan kembali akan rusak. a = True; True = 'i am an idiot'; a == True=> Salah. Selain penugasan kembali seperti itu, nilai-nilai standar distandarisasi sebagai 0 dan 1, dan saya percaya itu adalah praktik umum untuk bergantung pada itu; misalnya untuk mengindeks ke dalam array dua elemen, di mana [0] menyimpan kasus salah, [1] benar.
ToolmakerSteve
Saya hanya melihat konfirmasi resmi lain dari fakta bahwa True dalam praktiknya dapat dianggap sebagai 1 dan Salah 0: docs.python.org/2/library/stdtypes.html#boolean-values . Saya menambahkan ini ke jawaban ini.
Eric O Lebigot
77

Tautan ke PEP yang membahas jenis bool baru dengan Python 2.3: http://www.python.org/dev/peps/pep-0285/ .

Saat mengonversi bool ke int, nilai integer selalu 0 atau 1, tetapi saat mengubah int ke bool, nilai boolean bernilai True untuk semua bilangan bulat kecuali 0.

>>> int(False)
0
>>> int(True)
1
>>> bool(5)
True
>>> bool(-5)
True
>>> bool(0)
False
Erik Cederstrand
sumber
22

Dalam Python 2.x, tidak dijamin sama sekali:

>>> False = 5
>>> 0 == False
False

Jadi itu bisa berubah. Dalam Python 3.x, True, False, dan None adalah kata-kata yang dicadangkan , sehingga kode di atas tidak akan berfungsi.

Secara umum, dengan boolean Anda harus mengasumsikan bahwa sementara False akan selalu memiliki nilai integer 0 (selama Anda tidak mengubahnya, seperti di atas), True dapat memiliki nilai lain. Saya tidak akan selalu bergantung pada jaminan apa pun itu True==1, tetapi pada Python 3.x, ini akan selalu menjadi kasusnya, apa pun yang terjadi.

Daniel G
sumber
3
Re "True dapat memiliki nilai lain. Saya tidak perlu bergantung pada jaminan apa pun bahwa True == 1". Sebenarnya, Anda BISA mengandalkan True == 1, sesuai python.org/dev/peps/pep-0285 , dan spec docs.python.org/2/reference/… "Nilai Boolean berperilaku seperti nilai 0 dan 1, masing-masing , di hampir semua konteks ... "Saya tidak mengatakan tidak mungkin untuk menimpa ini di Py 2 dengan menetapkan kembali Benar atau Salah, tetapi saya mengatakan bahwa kecuali beberapa programmer pada proyek Anda adalah seorang idiot dan melakukan penugasan ulang seperti itu, perilaku dijamin.
ToolmakerSteve
-2

Sangat sederhana. Karena bool berhubungan dengan mengevaluasi integer sebagai bool, HANYA nol memberikan jawaban yang salah. SEMUA nilai-nilai Nol, mengapung, bilangan bulat, termasuk angka negatif, atau apa pun yang Anda miliki, akan kembali benar.

Contoh yang bagus mengapa ini berguna adalah menentukan status daya perangkat. Nyala adalah nilai bukan nol, off adalah nol. Berbicara secara elektronik ini masuk akal.

Untuk menentukan benar atau salah relatif antara nilai, Anda harus memiliki sesuatu untuk membandingkannya. Hal ini berlaku untuk string dan nilai-nilai nomor, menggunakan ==atau !=atau <, > >=, <=, dll

Anda bisa menetapkan integer ke variabel dan kemudian mendapatkan benar atau salah berdasarkan nilai variabel itu.

Kathy
sumber
1
Pertanyaannya adalah apakah True == 1 dijamin oleh Python, bukan tentang nilai boolean bilangan bulat.
Eric O Lebigot
-3

Cukup tulis int(False)dan Anda akan dapatkan 0, jika Anda mengetiknya int(True)akan ditampilkan1

Harsh Rathee
sumber
4
Ini hanya berarti bahwa False dan True adalah input yang valid untuk int(), dengan makna numerik sederhana, bukan bahwa mereka persis identik dengan 0 dan 1.
Eric O Lebigot
-5

Salah adalah omong kosong. Ini memiliki tipe yang berbeda. Ini adalah objek yang berbeda dari 0 yang merupakan bilangan bulat.

0 == Falsemengembalikan True karena False dilemparkan ke integer. int (Salah) mengembalikan 0

Dokumentasi python dari operator == mengatakan (bantuan ('==')):

Operator <, >, ==, >=, <=, dan !=membandingkan nilai dua benda. Objek tidak perlu memiliki tipe yang sama. Jika keduanya angka, mereka dikonversi ke tipe umum.

Sebagai akibatnya, False dikonversi menjadi integer untuk keperluan perbandingan. Tetapi berbeda dari 0.

>>> 0 is False
False
luc
sumber
26
Ini tidak sepenuhnya benar: booladalah subkelas dari int, jadi dalam arti yang sangat nyata, bool adalah bilangan bulat. Misalnya, isinstance(True, int)mengembalikan True. Dan pemeriksaan kesetaraan tidak mengubah bool menjadi int, karena tidak ada konversi yang diperlukan: ia hanya memanggil int.__cmp__langsung. Catatan yang bool.__cmp__ is int.__cmp__juga dievaluasi untuk True.
Mark Dickinson
3
-1 untuk jawaban ini. Deskripsi yang salah tentang hubungan antara bool dan int (dalam Python 2). isinstance(True, int)=> Benar. Yaitu, True IS integer, dan tidak memerlukan konversi.
ToolmakerSteve
Saya punya skrip yang mengembalikan False atau Int ... menggunakan while response is Falseberhasil, dan while response == Falsetidak .. Terima kasih!
curly_brackets
5
Itu 0 is Falsetidak benar memberitahumu apa-apa. Di penerjemah interaktif Anda, masukkan x = -10, lalu y = -10, lalu x is ydan itu juga akan salah. Hanya karena ada optimisasi di tempat di mana juru bahasa Python menggunakan kembali objek integer yang sama dalam keadaan tertentu (menyimpan literer integer sebagai konstanta, menginternir integer kecil) tidak berarti yang isharus digunakan ketika Anda ingin menguji kesetaraan nilai integer .
Martijn Pieters