Melihat ke Queue.py dengan Python 2.6, saya menemukan konstruksi yang menurut saya agak aneh:
def full(self):
"""Return True if the queue is full, False otherwise
(not reliable!)."""
self.mutex.acquire()
n = 0 < self.maxsize == self._qsize()
self.mutex.release()
return n
Jika maxsize
0 antrian tidak pernah penuh.
Pertanyaan saya adalah bagaimana cara kerjanya untuk kasus ini? Bagaimana 0 < 0 == 0
dianggap Salah?
>>> 0 < 0 == 0
False
>>> (0) < (0 == 0)
True
>>> (0 < 0) == 0
True
>>> 0 < (0 == 0)
True
>>> (0) < (0 == 0)
, jelas tidak.n = 0 < self.maxsize == self._qsize()
di tempat pertama, dalam bahasa apa pun. Jika mata Anda harus melesat bolak-balik melintasi garis beberapa kali untuk mencari tahu apa yang terjadi, itu bukan baris yang ditulis dengan baik. Pisahkan saja menjadi beberapa baris.Jawaban:
Saya percaya Python memiliki penanganan kasus khusus untuk urutan operator relasional untuk membuat perbandingan jangkauan mudah diungkapkan. Jauh lebih baik untuk mengatakan
0 < x <= 5
daripada mengatakan(0 < x) and (x <= 5)
.Ini disebut perbandingan berantai . Dan itu adalah tautan ke dokumentasi untuk mereka.
Dengan kasus lain yang Anda bicarakan, tanda kurung memaksa satu operator relasional diterapkan sebelum yang lain, sehingga mereka tidak lagi menjadi perbandingan berantai. Dan karena
True
danFalse
memiliki nilai sebagai bilangan bulat Anda mendapatkan jawaban yang Anda lakukan dari versi tanda kurung.sumber
Karena
(0 < 0) and (0 == 0)
adalah
False
. Anda dapat menyatukan operator perbandingan dan mereka secara otomatis diperluas menjadi perbandingan berpasangan.EDIT - klarifikasi tentang Benar dan Salah dengan Python
Dengan Python
True
danFalse
hanya contohbool
, yang merupakan subclass dariint
. Dengan kata lain,True
sebenarnya hanya 1.Intinya adalah Anda dapat menggunakan hasil perbandingan boolean persis seperti bilangan bulat. Ini mengarah pada hal-hal yang membingungkan seperti
>>> (1==1)+(1==1) 2 >>> (2<1)<1 True
Tapi ini hanya akan terjadi jika Anda mengurung perbandingan sehingga dievaluasi terlebih dahulu. Jika tidak, Python akan memperluas operator perbandingan.
sumber
'success' if result_code == 0 else 'failure'
dapat ditulis ulang karena('error', 'success')[result_code == 0]
, sebelumnya saya belum pernah melihat boolean yang digunakan untuk memilih item dalam daftar / tupel.Perilaku aneh yang Anda alami berasal dari kemampuan ular piton hingga kondisi rantai. Karena menemukan 0 tidak kurang dari 0, ia memutuskan bahwa seluruh ekspresi bernilai false. Segera setelah Anda memecahnya menjadi kondisi terpisah, Anda mengubah fungsinya. Ini pada dasarnya adalah mengujinya
a < b && b == c
untuk pernyataan asli Andaa < b == c
.Contoh lain:
>>> 1 < 5 < 3 False >>> (1 < 5) < 3 True
sumber
a < b && b == c
sama dengana < b == c
OO>>> 0 < 0 == 0 False
Ini adalah perbandingan yang dirantai. Ini mengembalikan nilai benar jika setiap perbandingan berpasangan pada gilirannya benar. Itu sama dengan
(0 < 0) and (0 == 0)
>>> (0) < (0 == 0) True
Ini sama dengan
0 < True
yang mengevaluasi ke True.>>> (0 < 0) == 0 True
Ini sama dengan
False == 0
yang mengevaluasi ke True.>>> 0 < (0 == 0) True
Setara dengan
0 < True
yang, seperti di atas, mengevaluasi ke True.sumber
Melihat pembongkaran (byte kode) itu jelas mengapa
0 < 0 == 0
adalahFalse
.Berikut adalah analisis dari ungkapan ini:
>>>import dis >>>def f(): ... 0 < 0 == 0 >>>dis.dis(f) 2 0 LOAD_CONST 1 (0) 3 LOAD_CONST 1 (0) 6 DUP_TOP 7 ROT_THREE 8 COMPARE_OP 0 (<) 11 JUMP_IF_FALSE_OR_POP 23 14 LOAD_CONST 1 (0) 17 COMPARE_OP 2 (==) 20 JUMP_FORWARD 2 (to 25) >> 23 ROT_TWO 24 POP_TOP >> 25 POP_TOP 26 LOAD_CONST 0 (None) 29 RETURN_VALUE
Perhatikan baris 0-8: Baris-baris ini memeriksa apakah
0 < 0
yang jelas kembaliFalse
ke tumpukan python.Sekarang perhatikan baris 11:
JUMP_IF_FALSE_OR_POP 23
Ini berarti bahwa jika0 < 0
kembaliFalse
melakukan lompatan ke baris 23.Sekarang,
0 < 0
adalahFalse
, jadi lompatan diambil, yang meninggalkan tumpukan denganFalse
yang merupakan nilai kembalian untuk seluruh ekspresi0 < 0 == 0
, meskipun== 0
bagian tersebut bahkan tidak dicentang.Jadi, untuk menyimpulkan, jawabannya seperti yang dikatakan dalam jawaban lain atas pertanyaan ini.
0 < 0 == 0
memiliki arti khusus. Kompilator mengevaluasi ini menjadi dua istilah:0 < 0
dan0 == 0
. Seperti halnya ekspresi boolean kompleks diand
antara mereka, jika yang pertama gagal maka yang kedua bahkan tidak dicentang.Berharap ini mencerahkan segalanya, dan saya sangat berharap metode yang saya gunakan untuk menganalisis perilaku tak terduga ini akan mendorong orang lain untuk mencoba hal yang sama di masa depan.
sumber
Seperti yang disebutkan orang lain
x comparison_operator y comparison_operator z
adalah gula sintaksis(x comparison_operator y) and (y comparison_operator z)
dengan bonus yang hanya dievaluasi sekali.Jadi ekspresi Anda
0 < 0 == 0
benar-benar(0 < 0) and (0 == 0)
mengevaluasiFalse and True
mana yang adilFalse
.sumber
mungkin kutipan dari dokumen ini dapat membantu:
Ini adalah perbandingan, tetapi karena Anda merangkai perbandingan, Anda harus tahu bahwa:
sumber
Ini dia, dengan segala kemuliaannya.
>>> class showme(object): ... def __init__(self, name, value): ... self.name, self.value = name, value ... def __repr__(self): ... return "<showme %s:%s>" % (self.name, self.value) ... def __cmp__(self, other): ... print "cmp(%r, %r)" % (self, other) ... if type(other) == showme: ... return cmp(self.value, other.value) ... else: ... return cmp(self.value, other) ... >>> showme(1,0) < showme(2,0) == showme(3,0) cmp(<showme 1:0>, <showme 2:0>) False >>> (showme(1,0) < showme(2,0)) == showme(3,0) cmp(<showme 1:0>, <showme 2:0>) cmp(<showme 3:0>, False) True >>> showme(1,0) < (showme(2,0) == showme(3,0)) cmp(<showme 2:0>, <showme 3:0>) cmp(<showme 1:0>, True) True >>>
sumber
Saya pikir Python melakukan itu aneh antara sihir. Sama seperti
1 < 2 < 3
mean 2 adalah antara 1 dan 3.Dalam kasus ini, menurut saya [tengah 0] lebih besar dari [kiri 0] dan sama dengan [kanan 0]. Tengah 0 tidak lebih besar dari kiri 0, sehingga bernilai false.
sumber