Patrząc na Queue.py w Pythonie 2.6, znalazłem tę konstrukcję, która wydała mi się nieco dziwna:
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
Jeśli maxsize
jest 0, kolejka nigdy nie jest pełna.
Moje pytanie brzmi, jak to działa w tym przypadku? Jak 0 < 0 == 0
jest uważane za fałsz?
>>> 0 < 0 == 0
False
>>> (0) < (0 == 0)
True
>>> (0 < 0) == 0
True
>>> 0 < (0 == 0)
True
>>> (0) < (0 == 0)
wyraźnie nie jest.n = 0 < self.maxsize == self._qsize()
w pierwszej kolejności, w żadnym języku. Jeśli twoje oczy muszą kilka razy przesuwać się w tę iz powrotem po linii, aby dowiedzieć się, co się dzieje, nie jest to dobrze napisana linia. Po prostu podziel go na kilka wierszy.Odpowiedzi:
Uważam, że Python obsługuje specjalne przypadki w sekwencjach operatorów relacyjnych, aby porównania zakresów były łatwe do wyrażenia. O wiele przyjemniej jest móc powiedzieć
0 < x <= 5
niż powiedzieć(0 < x) and (x <= 5)
.Nazywa się to porównaniami łańcuchowymi . A to jest link do dokumentacji dla nich.
W innych przypadkach, o których mówisz, nawiasy wymuszają zastosowanie jednego operatora relacji przed drugim, więc nie są one już połączonymi porównaniami. A ponieważ
True
iFalse
masz wartości jako liczby całkowite, otrzymujesz odpowiedzi z wersji ujętych w nawiasy.źródło
Ponieważ
jest
False
. Operatory porównania można łączyć w łańcuchy, które są automatycznie rozszerzane do porównań parami.EDYCJA - wyjaśnienie dotyczące prawdy i fałszu w Pythonie
W Pythonie
True
iFalse
są tylko instancjamibool
, które są podklasąint
. Innymi słowy,True
tak naprawdę to tylko 1.Chodzi o to, że wyniku porównania logicznego można używać dokładnie tak, jak liczby całkowitej. Prowadzi to do mylących rzeczy, takich jak
Ale to się stanie tylko wtedy, gdy umieścisz porównania w nawiasach, tak aby były oceniane jako pierwsze. W przeciwnym razie Python rozszerzy operatory porównania.
źródło
'success' if result_code == 0 else 'failure'
można przepisać, ponieważ('error', 'success')[result_code == 0]
przedtem nigdy nie widziałem wartości logicznej używanej do wybierania pozycji z listy / krotki.Dziwne zachowanie, którego doświadczasz, wynika ze zdolności Pythona do łączenia warunków. Ponieważ stwierdza, że 0 nie jest mniejsze niż 0, decyduje o tym, że całe wyrażenie ma wartość fałsz. Gdy tylko podzielisz to na osobne warunki, zmieniasz funkcjonalność. Początkowo zasadniczo testuje to
a < b && b == c
dla pierwotnego oświadczenia oa < b == c
.Inny przykład:
źródło
a < b && b == c
to to samo coa < b == c
OOTo porównanie łańcuchowe. Zwraca prawdę, jeśli po kolei każde porównanie parami jest prawdziwe. To jest odpowiednik
(0 < 0) and (0 == 0)
Jest to równoważne z
0 < True
wartością True.Jest to równoważne z
False == 0
wartością True.Odpowiednik, do
0 < True
którego, jak powyżej, przyjmuje wartość True.źródło
Patrząc na demontaż (kody bajtów) widać, dlaczego tak
0 < 0 == 0
jestFalse
.Oto analiza tego wyrażenia:
Zwróć uwagę na linie 0-8: te wiersze sprawdzają, czy
0 < 0
który oczywiście wracaFalse
na stos Pythona.Zwróćcie teraz uwagę na wiersz 11:
JUMP_IF_FALSE_OR_POP 23
Oznacza to, że jeśli0 < 0
zwraca,False
wykonuje skok do wiersza 23.Teraz
0 < 0
jestFalse
, więc wykonywany jest skok, który pozostawia stos zFalse
wartością zwracaną dla całego wyrażenia0 < 0 == 0
, nawet jeśli== 0
część nie jest nawet zaznaczona.Podsumowując, odpowiedź jest taka, jak w innych odpowiedziach na to pytanie.
0 < 0 == 0
ma specjalne znaczenie. Kompilator ocenia to na dwa warunki:0 < 0
i0 == 0
. Podobnie jak w przypadku każdego złożonego wyrażenia logicznego zand
między nimi, jeśli pierwsze zawiedzie, to drugie nie jest nawet sprawdzane.Mam nadzieję, że to trochę rozjaśnia sprawę i mam nadzieję, że metoda, której użyłem do analizy tego nieoczekiwanego zachowania, zachęci innych do spróbowania tego samego w przyszłości.
źródło
Jak wspomniano u innych,
x comparison_operator y comparison_operator z
jest to cukier syntaktyczny(x comparison_operator y) and (y comparison_operator z)
z premią, że y jest oceniane tylko raz.Więc twoje wyrażenie
0 < 0 == 0
jest naprawdę(0 < 0) and (0 == 0)
, które ocenia,False and True
które jest sprawiedliweFalse
.źródło
może ten fragment dokumentacji może pomóc:
To były porównania, ale ponieważ łączysz porównania łańcuchowe , powinieneś wiedzieć, że:
źródło
Oto ona, w całej okazałości.
źródło
Myślę, że Python robi to dziwnie między magią. To samo, co
1 < 2 < 3
oznacza, że 2 jest między 1 a 3.W tym przypadku myślę, że wykonanie [środkowe 0] jest większe niż [lewe 0] i równe [prawe 0]. Środkowe 0 nie jest większe niż lewe 0, więc przyjmuje wartość fałsz.
źródło