Чи є False == 0 та True == 1 деталі реалізації чи це гарантується мовою?


244

Чи гарантовано це, False == 0і True == 1в Python (якщо припустити, що вони не призначені користувачем)? Наприклад, чи гарантується якимось чином, що наступний код завжди дасть однакові результати, незалежно від версії Python (як існуючої, так і, ймовірно, майбутньої)?

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

Будь-яка посилання на офіційну документацію буде дуже вдячна!

Правка : Як зазначено у багатьох відповідях, boolуспадковується від int. Отже, питання може бути перероблено так: "Чи офіційно в документації говориться про те, що програмісти можуть розраховувати на булі, що успадковуються з цілих чисел, зі значеннями 0і1 ?". Це питання актуально для написання надійного коду, який не вийде з-за деталей про реалізацію!


63
@ S.Lott: Є багато причин, щоб задати питання вище. Таким чином, є випадки, коли посилання на булеві цілі числа робить ваш код простішим: чи потрібно це змінювати? Або ви можете помітити місця в коді, написаному кимось іншим, який покладається на булеві числа, які є цілими числами: чи ви перериваєте те, що ви змінюєте в коді, щоб "виправити" існуючий код, або можете бути впевнені, що поточне кодування звучить ? Існує безліч інших прикладів. Загалом, добре знати правила гри, щоб ви могли добре її грати та програмувати.
Ерік О Лебігот

10
@ S.Lott: Оригінальна публікація точно перегукується з вашою точкою: по суті, питання "Чи це деталізація щодо реалізації?", Оскільки я повністю згоден з вами на думці, що не слід залежати від деталей реалізації. Якщо булевики є офіційно цілими числами відомих значень, то код у питанні не покладається на деталі реалізації, що добре.
Ерік О Лебігот

5
@S. Лот: Знаючи, що False == 0 та True == 1 полегшує підрахунок, скільки булів у послідовності є істинними: Ви можете просто написати sum(bool_list). Інакше вам доведеться писати sum(1 for x bool_list if x).
dan04

8
@dan: Це один із способів підрахунку булів. Я б сказав, що bool_list.count(True)це явніше; це також приблизно в 3 рази швидше… :)
Ерік О Лебіго

2
@akonsu Як показують відповіді, булеви Python - це насправді (специфічний підклас) цілих чисел. Крім того, Python, очевидно, має типи; можливо, ви мали на увазі, що це "не статично набрано"? Крім того, я не впевнений, що ви маєте на увазі під "я б не робив помилок у коді". Тепер я ніколи не люблю змішувати булеві числа з цілими числами, оскільки вони концептуально різні, і я б не заперечував, якби булеви Python були не цілими числами, але знаючи, що вони є зі значеннями 0 і 1, це корисно.
Ерік О Лебігот

Відповіді:


183

У Python 2.x це так не гарантується, оскільки це можливо для TrueтаFalse бути змінені. Однак, навіть якщо це трапляється, булеві True та булеві False все одно належним чином повертаються для порівняння.

У Python 3.x True і Falseє ключові слова і завжди будуть рівні 1та0 .

За звичайних обставин у Python 2 та завжди в Python 3:

Falseоб'єкт типу, boolякий є підкласомint :

object
   |
 int
   |
 bool

Це єдина причина, чому у вашому прикладі ['zero', 'one'][False]працює. Він би не працював з об'єктом, який не є підкласом цілого числа, тому що індексація списку працює лише з цілими числами, або з об'єктами, що визначають __index__метод (завдяки mark-dickinson ).

Редагувати:

Це стосується поточної версії python та версії для Python 3. Документи для python 2.6 та документи для Python 3 кажуть:

Існує два типи цілих чисел: [...] Цілі (int) [...] булеві (bool)

і в бульовому підрозділі:

Булеві значення: вони представляють значення істинності False and True [...] Булеві значення ведуть себе як значення 0 та 1 відповідно майже у всіх контекстах, виняток становить лише те, що при перетворенні на рядок, рядки "False" або "True "повертаються відповідно.

Існує також для Python 2 :

У числових контекстах (наприклад, коли вони використовуються як аргумент для арифметичного оператора), вони [False та True] поводяться як цілі числа 0 і 1 відповідно.

Отже, булеви явно розглядаються як цілі числа в Python 2.6 та 3.

Тож ви в безпеці, поки не прийде Python 4. ;-)


2
0 == 0,0 повертає значення True, тоді як ['нуль', 'one'] [0.0] не вдається. ['zero', 'one'] [False] працює, оскільки bool є підкласом int. (int .__ підкласи __ () повертає [<type 'bool'>])
luc

20
Nitpick: будь-який об’єкт, що забезпечує __index__метод, може використовуватися як індекс списку; не лише підкласи intабо long.
Марк Дікінсон

Ага так, це теж є. Але було б краще не посилатися на документацію Python 3.0: 3.0 мертвий. :)
Марк Дікінсон

4
Re: "У Python 2.x це не гарантується, оскільки можливо переназначити True та False". ІМХО, хоча це правда, кожен, хто перепризначить Істину чи Неправду, заслуговує на будь-які дивні наслідки, які вони отримають. Зокрема, зберігання True перед переназначенням, а потім порівняння результату з Істинним після перепризначення порушиться. a = True; True = 'i am an idiot'; a == True=> Неправдиво. Окрім такого перепризначення, значення за замовчуванням стандартизовані як 0 та 1, і я вважаю, що звичайна практика залежить від цього; наприклад, індексувати на двоелементний масив, де [0] містить помилковий випадок, [1] true.
ToolmakerSteve

Я щойно помітив ще одне офіційне підтвердження того, що True на практиці можна вважати як 1 та False 0: docs.python.org/2/library/stdtypes.html#boolean-values . Я додаю це до цієї відповіді.
Ерік О Лебігот

78

Посилання на PEP, обговорюючи новий тип bool в Python 2.3: http://www.python.org/dev/peps/pep-0285/ .

При перетворенні bool в int ціле число завжди дорівнює 0 або 1, але при перетворенні int в bool булеве значення відповідає True для всіх цілих чисел, крім 0.

>>> int(False)
0
>>> int(True)
1
>>> bool(5)
True
>>> bool(-5)
True
>>> bool(0)
False

22

У Python 2.x це зовсім не гарантується:

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

Так це могло змінитися. У Python 3.x, True, False та None є зарезервованими словами , тому наведений вище код не працює.

Загалом, з булевими ви повинні вважати, що хоча False завжди матиме ціле значення 0 (до тих пір, поки ви не зміните його, як вище), True може мати будь-яке інше значення. Я б не обов'язково покладався на будь-які гарантії, що True==1, але на Python 3.x, це завжди буде так, незалежно від того.


3
Re "True може мати будь-яке інше значення. Я б не обов'язково покладатися на будь-які гарантії, що True == 1". Власне, МОЖЕТЕ покластися на True == 1, відповідно до python.org/dev/peps/pep-0285 та spec docs.python.org/2/reference/… "Булеві значення ведуть себе як значення 0 та 1 відповідно майже у всіх контекстах ... "Я не кажу, що неможливо переосмислити це в Py 2, перепризначивши правду чи помилково, але я кажу, що, якщо якийсь програміст у вашому проекті не ідіот і не перекладе такий перелік, поведінка гарантована.
ToolmakerSteve

-2

Дуже просто. Оскільки bool відноситься до оцінки цілого числа як bool, ТОЛЬКО нуль дає хибну відповідь. ВСІ ненульові значення, плавці, цілі числа, включаючи від’ємні числа, чи що у вас є, повернуть істинні.

Гарний приклад, чому це корисно, - це визначення рівня живлення пристрою. Увімкнено будь-яке ненульове значення, вимкнено - нуль. В електронному плані це має сенс.

Щоб визначити істинне чи помилкове відносно між значеннями, ви повинні мати з чим порівняти його. Це відноситься до рядків і числових значень, використовуючи ==або !=або <, > >=,<= і т.д.

Ви можете призначити цілому змінній, а потім отримати істинне або хибне на основі цього значення змінної.


1
Питання в тому, чи гарантується True == 1 Python, а не про булеве значення цілих чисел.
Ерік О Лебігот

-3

Просто напишіть, int(False)і ви отримаєте 0, якщо ви введете int(True)це буде виводити1


4
Це означає лише те, що False та True є дійсними введеннями до int()простого числового значення, не те, що вони точно ідентичні 0 і 1.
Ерік О Лебігот

-5

Неправдивий - бул. Він має інший тип. Це інший об'єкт від 0, який є цілим числом.

0 == Falseповертає True, тому що False приведено до цілого числа. int (False) повертає 0

Документація пітона оператора == говорить (help ('==')):

Оператори <, >, ==, >=, <=, і !=порівняти значення двох об'єктів. Об'єкти не повинні мати одного типу. Якщо обидва - це числа, вони перетворюються на загальний тип.

Як наслідок, False перетворюється на ціле число для потреби порівняння. Але він відрізняється від 0.

>>> 0 is False
False

26
Це не зовсім правильно: boolє підкласом int, тому в абсолютно реальному сенсі bool є цілим числом. Наприклад, isinstance(True, int)повертає True. І перевірка рівності не перетворює bool в int, оскільки перетворення не потрібно: він просто викликає int.__cmp__безпосередньо. Зауважте, що bool.__cmp__ is int.__cmp__також оцінюється до True.
Марк Дікінсон

3
-1 для цієї відповіді. Неправильний опис взаємозв'язку між bool та int (у Python 2). isinstance(True, int)=> Правда. Тобто, True IS цілого, і не вимагає перетворень.
ToolmakerSteve

У мене був сценарій, який повертав False or Int ... використовуючи while response is Falseпрацював, а while response == Falseне .. Дякую!
curly_brackets

5
Це 0 is Falseнеправда нічого не говорить вам. В інтерактивному інтерпретатор, введіть x = -10, потімy = -10 , тоді, x is yі це також буде помилковим. Тільки тому, що існують оптимізації, коли інтерпретатор Python повторно використовує ті самі цілі об'єкти за певних обставин (зберігання цілих цілих букв як константи, інтернування малих цілих чисел) не означає, що їх isслід використовувати, коли ви хочете перевірити цілісні значення рівності.
Martijn Pieters
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.