Czy False == 0 i True == 1 jest szczegółem implementacji, czy jest to gwarantowane przez język?

244

Czy jest to zagwarantowane False == 0i True == 1w Pythonie (zakładając, że użytkownik nie przypisuje ich ponownie)? Na przykład, czy jest w jakikolwiek sposób gwarantowany, że poniższy kod zawsze będzie dawał takie same wyniki, bez względu na wersję Pythona (zarówno istniejące, jak i prawdopodobnie przyszłe)?

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

Wszelkie odniesienia do oficjalnej dokumentacji będą mile widziane!

Edycja : jak zauważono w wielu odpowiedziach, booldziedziczy po int. Pytanie może zatem zostać przekształcone w następujący sposób: „Czy dokumentacja oficjalnie mówi, że programiści mogą polegać na wynikach logicznych dziedziczących po liczbach całkowitych, z wartościami 0i1 ?”. To pytanie dotyczy pisania solidnego kodu, który nie zawiedzie z powodu szczegółów implementacji!

Eric O Lebigot
źródło
63
@ S.Lott: Istnieje wiele powodów, by zadać powyższe pytanie. Tak więc są przypadki, w których poleganie na liczbach całkowitych jako liczbach całkowitych upraszcza kod: czy musisz go zmienić? Lub możesz zauważyć miejsca w kodzie napisanym przez kogoś innego, kto polega na liczbach całkowitych jako liczbach całkowitych: czy przerywasz to, co modyfikujesz w kodzie, aby „naprawić” istniejący kod, czy masz pewność, że bieżące kodowanie jest prawidłowe ? Istnieje wiele innych przykładów. Mówiąc bardziej ogólnie, dobrze jest znać zasady gry, aby można było w nią dobrze grać i programować w rozsądny sposób.
Eric O Lebigot,
10
@ S.Lott: Oryginalny post dokładnie odzwierciedla twój punkt widzenia: pytanie brzmi zasadniczo: „Czy to szczegół wdrożenia?”, Ponieważ w pełni zgadzam się z Tobą co do tego, że nie należy polegać na szczegółach wdrożenia. Jeśli booleany są oficjalnie liczbami całkowitymi o znanych wartościach, to kod w pytaniu nie opiera się na szczegółach implementacji, co jest dobre.
Eric O Lebigot,
5
@S. Lot: Wiedza, że ​​Fałsz == 0 i Prawda == 1 ułatwia policzenie, ile boolów w sekwencji jest prawdą: Możesz po prostu pisać sum(bool_list). W przeciwnym razie będziesz musiał pisać sum(1 for x bool_list if x).
dan04,
8
@dan: To jeden ze sposobów liczenia wartości logicznych. Powiedziałbym, że bool_list.count(True)jest to bardziej wyraźne; jest także około 3 razy szybszy… :)
Eric O Lebigot,
2
@akonsu Jak pokazują odpowiedzi, booleany Pythona są w rzeczywistości (konkretną podklasą) liczbami całkowitymi. Co więcej, Python oczywiście ma typy; może miałeś na myśli, że nie jest on „wpisany statycznie”? Nie jestem też pewien, co rozumiesz przez „nie popełniam błędów w kodzie”. Teraz nigdy nie lubię mieszać boolanów z liczbami całkowitymi, ponieważ są one koncepcyjnie różne i nie miałbym nic przeciwko, gdyby booleany w Pythonie nie były liczbami całkowitymi, ale wiedza, że ​​są, z wartościami 0 i 1, jest przydatna.
Eric O Lebigot,

Odpowiedzi:

183

W Pythonie 2.x nie jest to gwarantowane, ponieważ jest możliwe Truei Falsemożna je ponownie przypisać. Jednak nawet jeśli tak się stanie, wartość logiczna Prawda i wartość logiczna False są nadal poprawnie zwracane do porównań.

W Pythonie 3.x Truei Falsesą słowami kluczowymi i zawsze będą równe 1i 0.

W normalnych okolicznościach w Python 2 i zawsze w Python 3:

Falseobiekt jest typu, boolktóry jest podklasą int:

object
   |
 int
   |
 bool

Jest to jedyny powód, dla którego w twoim przykładzie ['zero', 'one'][False]działa. Nie działałby z obiektem, który nie jest podklasą liczb całkowitych, ponieważ indeksowanie list działa tylko z liczbami całkowitymi lub obiektami, które definiują __index__metodę (dzięki mark-dickinson ).

Edytować:

Dotyczy to zarówno bieżącej wersji Pythona, jak i wersji Python 3. Zarówno dokumentacja Pythona 2.6, jak i dokumentacja Pythona 3 mówią:

Istnieją dwa typy liczb całkowitych: [...] Liczby całkowite (int) [...] Booleans (bool)

oraz w podsekcji boolowskiej:

Wartości logiczne: reprezentują one wartości prawdy Fałsz i Prawda [...] Wartości boolowskie zachowują się jak odpowiednio wartości 0 i 1, w prawie wszystkich kontekstach, z wyjątkiem tego, że po przekształceniu na ciąg, ciągi znaków „Fałsz” lub „Prawda” ”są zwracane odpowiednio.

Istnieje również, w przypadku Python 2 :

W kontekstach numerycznych (na przykład jako argument operatora arytmetycznego) zachowują się one [False i True] odpowiednio jako liczby całkowite 0 i 1.

Tak więc booleany są jawnie uważane za liczby całkowite w Pythonie 2.6 i 3.

Więc jesteś bezpieczny, dopóki nie pojawi się Python 4. ;-)

Olivier Verdier
źródło
2
0 == 0,0 zwraca wartość Prawda, podczas gdy [„zero”, „jeden”] [0,0] kończy się niepowodzeniem. [„zero”, „one”] [False] działa, ponieważ bool jest podklasą int. (int .__ podklasy __ () zwraca [<type 'bool'>])
luc
20
Nitpick: każdy obiekt udostępniający __index__metodę może być używany jako indeks listy; nie tylko podklasy intlub long.
Mark Dickinson
Ach tak, to też tam jest. Ale lepiej byłoby nie linkować do dokumentacji Python 3.0: 3.0 nie żyje. :)
Mark Dickinson,
4
Odp: „W Pythonie 2.x nie jest to gwarantowane, ponieważ możliwe jest ponowne przypisanie wartości Prawda i Fałsz”. IMHO, chociaż jest to prawda, każdy, kto ponownie przypisuje Prawdę lub Fałsz, zasługuje na wszelkie dziwne konsekwencje. W szczególności przechowywanie wartości True przed zmianą przypisania, a następnie porównywanie wyniku z wartością True po zmianie przypisania, spowodowałoby uszkodzenie. a = True; True = 'i am an idiot'; a == True=> Fałsz. Poza takim przeniesieniem wartości domyślne są znormalizowane jako 0 i 1 i uważam, że powszechną praktyką jest poleganie na tym; np. aby zindeksować tablicę dwuelementową, gdzie [0] zawiera fałszywy przypadek, [1] prawda.
ToolmakerSteve
Właśnie zauważyłem inne oficjalne potwierdzenie faktu, że True można w praktyce uznać za 1 i False 0: docs.python.org/2/library/stdtypes.html#boolean-values . Dodaję to do tej odpowiedzi.
Eric O Lebigot
78

Link do PEP omawiającego nowy typ bool w Pythonie 2.3: http://www.python.org/dev/peps/pep-0285/ .

Podczas konwertowania wartości bool na liczbę całkowitą wartość całkowita wynosi zawsze 0 lub 1, ale podczas konwertowania liczby całkowitej na wartość boolową wartość logiczna ma wartość True dla wszystkich liczb całkowitych oprócz 0.

>>> int(False)
0
>>> int(True)
1
>>> bool(5)
True
>>> bool(-5)
True
>>> bool(0)
False
Erik Cederstrand
źródło
22

W Pythonie 2.x nie ma żadnej gwarancji:

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

Więc to może się zmienić. W Pythonie 3.x prawda, fałsz i brak są słowami zastrzeżonymi , więc powyższy kod nie zadziała.

Ogólnie rzecz biorąc, w przypadku wartości logicznych należy założyć, że chociaż wartość False będzie zawsze miała wartość całkowitą równą 0 (o ile jej nie zmienisz, jak wyżej), wartość True może mieć dowolną inną wartość. Niekoniecznie polegałbym na jakiejkolwiek gwarancji True==1, ale w przypadku Python 3.x zawsze tak będzie, bez względu na wszystko.

Daniel G.
źródło
3
Re „True może mieć jakąkolwiek inną wartość. Niekoniecznie polegam na żadnej gwarancji, że True == 1”. W rzeczywistości MOŻESZ polegać na True == 1, zgodnie z python.org/dev/peps/pep-0285 i spec docs.python.org/2/reference/… "Wartości boolowskie zachowują się jak odpowiednio wartości 0 i 1 , w prawie wszystkich kontekstach ... „Nie twierdzę, że nie można tego zmienić w Py 2 poprzez zmianę przypisania Prawda lub Fałsz, ale mówię, że jeśli jakiś programista w twoim projekcie nie jest idiotą i nie dokonuje takiego przeniesienia, zachowanie jest gwarantowane.
ToolmakerSteve
-2

Bardzo prosty. Ponieważ bool odnosi się do oceny liczby całkowitej jako bool, TYLKO zero daje fałszywą odpowiedź. WSZYSTKIE wartości niezerowe, zmiennoprzecinkowe, liczby całkowite, w tym liczby ujemne lub to, co masz, zwróci wartość true.

Dobrym przykładem tego, dlaczego jest to przydatne, jest określenie stanu zasilania urządzenia. On to dowolna wartość niezerowa, off to zero. Ma to sens elektroniczny.

Aby ustalić wartość true lub false względnie między wartościami, musisz mieć coś do porównania. Odnosi się to do łańcuchów i wartości liczbowych, za pomocą ==lub !=lub <, > >=, <=, itd.

Możesz przypisać liczbę całkowitą do zmiennej, a następnie uzyskać wartość true lub false na podstawie tej wartości zmiennej.

Kathy
źródło
1
Pytanie dotyczy tego, czy Python gwarantuje True == 1, a nie logicznej wartości liczb całkowitych.
Eric O Lebigot,
-3

Po prostu napisz, int(False)a dostaniesz 0, jeśli wpiszesz int(True), wyświetli1

Surowy Rathee
źródło
4
Oznacza to tylko, że Fałsz i Prawda są prawidłowymi int()
danymi
-5

Fałsz to bool. Ma inny typ. Jest to obiekt inny niż 0, który jest liczbą całkowitą.

0 == Falsezwraca True, ponieważ False jest rzutowany na liczbę całkowitą. int (False) zwraca 0

Dokumentacja Pythona operatora == mówi (pomoc ('==')):

Operatorzy <, >, ==, >=, <=, i !=porównać wartości z dwóch obiektów. Obiekty nie muszą mieć tego samego typu. Jeśli oba są liczbami, są konwertowane na typ wspólny.

W związku z tym False jest konwertowany na liczbę całkowitą na potrzeby porównania. Ale różni się od 0.

>>> 0 is False
False
luc
źródło
26
To nie jest całkiem właściwe: booljest podklasą int, więc w bardzo realnym sensie bool jest liczbą całkowitą. Na przykład isinstance(True, int)zwraca True. A kontrola równości nie przekształca wartości bool na liczbę całkowitą, ponieważ konwersja nie jest konieczna: po prostu wywołuje int.__cmp__bezpośrednio. Uwaga, że bool.__cmp__ is int.__cmp__również ocenia True.
Mark Dickinson
3
-1 dla tej odpowiedzi. Niepoprawny opis zależności między bool i int (w Python 2). isinstance(True, int)=> Prawda. Oznacza to, że True IS jest liczbą całkowitą i nie wymaga konwersji.
ToolmakerSteve
Miałem skrypt, który zwrócił False lub Int ... używając while response is Falsedziałał, i while response == Falsenie zrobił ... Dzięki!
curly_brackets 23.04.16
5
To 0 is Falsefałsz nic ci nie mówi. W interaktywnym interpretera, należy wprowadzić x = -10, a następnie y = -10, po czym x is yi że będzie również być fałszywe. To, że istnieją optymalizacje, w których interpreter Pythona ponownie wykorzystuje te same obiekty liczb całkowitych w pewnych okolicznościach (przechowywanie literałów całkowitych jako stałych, internowanie małych liczb całkowitych), nie oznacza, że isnależy tego użyć, gdy chcesz przetestować równość wartości całkowitych .
Martijn Pieters