Является ли False == 0 и True == 1 деталями реализации или это гарантировано языком?

245

Гарантируется ли это 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 облегчает подсчет истинного числа bools в последовательности: вы можете просто написать sum(bool_list). В противном случае вам придется написать sum(1 for x bool_list if x).
dan04
8
@dan: Это один из способов подсчета логических значений. Я бы сказал, что bool_list.count(True)это более явно; это также примерно в 3 раза быстрее… :)
Eric O Lebigot
2
@akonsu Как показывают ответы, логические значения Python на самом деле являются (целым подклассом) целыми числами. Кроме того, у Python явно есть типы; может ты имел ввиду что он "не статически типизирован"? Кроме того, я не уверен, что вы подразумеваете под "я не буду делать ошибки в коде". Теперь мне никогда не нравится смешивать логические значения с целыми числами, потому что они концептуально отличаются, и я не возражаю, если бы логические значения Python не были целыми числами, но полезно знать, что они имеют значения 0 и 1.
Эрик О Лебиго

Ответы:

184

В 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 говорят:

Существует два типа целых чисел: [...] Integer (int) [...] Booleans (bool)

и в логическом подразделе:

Booleans: они представляют значения истинности False и True [...] логические значения ведут себя как значения 0 и 1, соответственно, почти во всех контекстах, за исключением того, что при преобразовании в строку строки «False» или «True возвращаются, соответственно.

Для Python 2 также есть :

В числовом контексте (например, при использовании в качестве аргумента арифметического оператора) они [False и True] ведут себя как целые числа 0 и 1 соответственно.

Таким образом, логические значения явно рассматриваются как целые числа в Python 2.6 и 3.

Так что вы в безопасности, пока не появится Python 4. ;-)

Оливье Вердиер
источник
2
0 == 0.0 возвращает True, в то время как ['zero', 'one'] [0.0] завершается ошибкой. ['zero', 'one'] [False] работает, потому что bool является подклассом int. (int .__ подклассы __ () возвращает [<type 'bool'>])
Люк
20
Nitpick: любой объект, который предоставляет __index__метод, может использоваться как индекс списка; не только подклассы intили long.
Марк Дикинсон
Ах да, это тоже там. Но было бы лучше не ссылаться на документацию по Python 3.0: 3.0 не работает. :)
Марк Дикинсон
4
Re: «В Python 2.x это не гарантируется, поскольку для True и False возможно переназначение». ИМХО, хотя это правда, любой, кто переназначает True или False, заслуживает любых странных последствий, которые они получают. В частности, сохранение True до переназначения и последующее сравнение результата с 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, переназначая True или False, но я говорю, что если какой-то программист в вашем проекте не идиот и не делает такое переназначение, поведение гарантировано.
ToolmakerSteve
-2

Очень просто. Поскольку bool относится к оценке целого числа как bool, ТОЛЬКО ноль дает ложный ответ. ВСЕ Ненулевые значения, числа с плавающей запятой, целые числа, включая отрицательные числа, или что у вас есть, вернут true.

Хорошим примером того, почему это полезно, является определение состояния питания устройства. On - любое ненулевое значение, off - ноль. В электронном виде это имеет смысл.

Чтобы определить true или false относительно значений, у вас должно быть что-то для сравнения. Это относится к строкам и числовых значений, используя ==или !=или <, > >=, <=и т.д.

Вы можете назначить целое число переменной, а затем получить значение true или false на основе значения этой переменной.

Кэти
источник
1
Вопрос в том, гарантируется ли True == 1 Python, а не в логическом значении целых чисел.
Эрик О Лебиго
-3

Просто напишите, int(False)и вы получите 0, если вы напечатаете, int(True)он будет выводить1

Суровый рати
источник
4
Это означает только то, что False и True являются допустимыми входными данными int(), с простым числовым значением, а не то, что они точно идентичны 0 и 1.
Eric O Lebigot
-5

Ложь это бул. У него другой тип. Это отличный от 0 объект, который является целым числом.

0 == Falseвозвращает True, потому что False приводится к целому числу. int (False) возвращает 0

Документация Python об операторе == гласит (help ('==')):

Операторы <, >, ==, >=, <=, и !=сравнить значения двух объектов. Объекты не обязательно должны быть одного типа. Если оба числа, они преобразуются в общий тип.

Как следствие, False преобразуется в целое число для сравнения. Но это отличается от 0.

>>> 0 is False
False
Luc
источник
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 или Int ... используя while response is Falseработал, и while response == Falseне .. Спасибо!
curly_brackets
5
Это 0 is Falseложно, ничего вам не говорит. В вашем интерактивном переводчике введите x = -10, затем y = -10, тогда, x is yи это также будет ложным. Тот факт, что существуют определенные оптимизации, когда интерпретатор Python повторно использует одни и те же целочисленные объекты в определенных обстоятельствах (хранение целочисленных литералов в качестве констант, интернирование небольших целых чисел), не означает, что это isследует использовать, когда вы хотите проверить на равенство целочисленных значений .
Мартин Питерс