False == 0 e True == 1 são detalhes de implementação ou são garantidos pelo idioma?


244

É garantido que False == 0e True == 1, em Python (assumindo que eles não foram reatribuídos pelo usuário)? Por exemplo, é de alguma forma garantido que o código a seguir sempre produzirá os mesmos resultados, independentemente da versão do Python (existente e, provavelmente, futura)?

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

Qualquer referência à documentação oficial seria muito apreciada!

Editar : Como observado em muitas respostas, boolherda de int. A questão pode, portanto, ser reformulada como: "A documentação diz oficialmente que os programadores podem confiar em booleanos herdados de números inteiros, com os valores 0e1 ?". Esta pergunta é relevante para escrever código robusto que não falhará devido aos detalhes da implementação!


63
@ S.Lott: Existem muitas razões para fazer a pergunta acima. Portanto, há casos em que confiar no fato de os booleanos serem inteiros torna seu código mais simples: você precisa alterá-lo? Ou você pode localizar lugares em um código escrito por outra pessoa que depende de booleanos como números inteiros: interrompe o que está modificando no código para "consertar" o código existente ou pode ter certeza de que a codificação atual está correta ? Há uma infinidade de outros exemplos. De um modo mais geral, é bom conhecer as regras do jogo, para que você possa jogar bem e programar de maneira sólida.
Eric O Lebigot 5/05

10
@ S.Lott: O post original ecoa exatamente o seu ponto: a questão é essencialmente "Isso é um detalhe da implementação?", Porque concordo plenamente com você na idéia de que não se deve depender dos detalhes da implementação. Se os booleanos são oficialmente inteiros de valores conhecidos, o código na pergunta não depende de detalhes de implementação, o que é bom.
Eric O Lebigot 5/05

5
@S. Lote: saber que Falso == 0 e Verdadeiro == 1 facilita a contagem de quantos bools em uma sequência são verdadeiros: Você pode simplesmente escrever sum(bool_list). Caso contrário, você teria que escrever sum(1 for x bool_list if x).
dan04

8
@dan: Essa é uma maneira de contar booleanos. Eu diria que bool_list.count(True)é mais explícito; é também sobre 3 vezes mais rápido ... :)
Eric O Lebigot

2
@akonsu Como mostram as respostas, os booleanos Python são na verdade (uma subclasse específica) de números inteiros. Além disso, o Python obviamente tem tipos; talvez você quis dizer que "não é estaticamente digitado"? Além disso, não tenho certeza do que você quer dizer com "Eu não cometeria erros no código". Agora, eu nunca gosto de misturar booleanos com números inteiros, porque eles são conceitualmente diferentes, e eu não me importaria se os booleanos Python não fossem números inteiros, mas saber que são, com os valores 0 e 1, é útil.
Eric O Lebigot

Respostas:


183

No Python 2.x, isso não é garantido, pois é possível Truee Falsereatribuído. No entanto, mesmo se isso acontecer, o booleano True e o booleano False ainda serão retornados corretamente para comparações.

Em Python 3.x Truee Falsesão palavras-chave e será sempre igual a 1e 0.

Sob circunstâncias normais no Python 2 e sempre no Python 3:

FalseO objeto é do tipo boolque é uma subclasse de int:

object
   |
 int
   |
 bool

É a única razão pela qual, no seu exemplo, ['zero', 'one'][False]funciona. Não funcionaria com um objeto que não seja uma subclasse de número inteiro, porque a indexação de lista funciona apenas com números inteiros ou objetos que definem um __index__método (obrigado mark-dickinson ).

Editar:

É verdade para a versão atual do python e para a do Python 3. Os documentos para o python 2.6 e os documentos para o Python 3 dizem:

Existem dois tipos de números inteiros: [...] Inteiros (int) [...] Booleanos (bool)

e na subseção booleana:

Booleanos: Representam os valores verdadeiros Falso e Verdadeiro [...] Os valores booleanos se comportam como os valores 0 e 1, respectivamente, em quase todos os contextos, exceto que, quando convertidos em uma sequência, as sequências "False" ou "True "são retornados, respectivamente.

Há também, para Python 2 :

Em contextos numéricos (por exemplo, quando usado como argumento para um operador aritmético), eles [False e True] se comportam como os números inteiros 0 e 1, respectivamente.

Portanto, os booleanos são explicitamente considerados como números inteiros no Python 2.6 e 3.

Então você estará seguro até o Python 4 aparecer. ;-)


2
0 == 0.0 retorna True enquanto ['zero', 'one'] [0.0] falha. ['zero', 'um'] [Falso] funciona porque bool é uma subclasse de int. (int .__ subclasses __ () retorna [<tipo 'bool'>])
luc

20
Nitpick: qualquer objeto que fornece um __index__método pode ser usado como um índice de lista; não apenas subclasses de intou long.
Mark Dickinson

Ah sim, também está lá. Mas seria melhor não vincular à documentação do Python 3.0: 3.0 está morto. :)
Mark Dickinson

4
Re: "No Python 2.x isso não é garantido, pois é possível reatribuir True e False". IMHO, enquanto isso é verdade, quem reatribui Verdadeiro ou Falso merece quaisquer consequências estranhas que obtenha. Especificamente, o armazenamento de True antes da reatribuição e, em seguida, a comparação do resultado com True após a reatribuição seria interrompido. a = True; True = 'i am an idiot'; a == True=> Falso. Além dessa reatribuição, os valores padrão são padronizados como 0 e 1, e acredito que é prática comum depender disso; por exemplo, para indexar em uma matriz de dois elementos, onde [0] contém o caso falso, [1] true.
Página

Acabei de notar outra confirmação oficial do fato de que True pode na prática ser considerado como 1 e Falso 0: docs.python.org/2/library/stdtypes.html#boolean-values . Estou adicionando isso a esta resposta.
Eric O Lebigot

77

Link para o PEP discutindo o novo tipo de bool no Python 2.3: http://www.python.org/dev/peps/pep-0285/ .

Ao converter um booleano em um int, o valor inteiro é sempre 0 ou 1, mas ao converter um int em um booliano, o valor booleano é True para todos os números inteiros, exceto 0.

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

22

No Python 2.x, isso não é garantido:

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

Então isso pode mudar. No Python 3.x, True, False e None são palavras reservadas , portanto o código acima não funcionaria.

Em geral, com os booleanos, você deve assumir que, embora False sempre tenha um valor inteiro 0 (desde que você não o altere, como acima), True pode ter qualquer outro valor. Eu não confiaria necessariamente em nenhuma garantia de que True==1, mas no Python 3.x, esse sempre será o caso, não importa o quê.


3
Re "True poderia ter outro valor. Eu não confiaria necessariamente em nenhuma garantia de que True == 1". Na verdade, você PODE confiar em True == 1, conforme python.org/dev/peps/pep-0285 , e spec docs.python.org/2/reference/… "Os valores booleanos se comportam como os valores 0 e 1, respectivamente , em quase todos os contextos ... "Não estou dizendo que é impossível substituir isso no Py 2 reatribuindo True ou False, mas estou dizendo que, a menos que algum programador do seu projeto seja um idiota e faça essa reatribuição, o comportamento é garantido.
Home

-2

Muito simples. Como bool se refere à avaliação de um número inteiro como bool, ONLY zero fornece uma resposta falsa. TODOS os valores diferentes de zero, valores flutuantes, números inteiros, incluindo números negativos ou o que você possui, retornará true.

Um bom exemplo de por que isso é útil é determinar o status de energia de um dispositivo. On é qualquer valor diferente de zero, off é zero. Eletronicamente, isso faz sentido.

Para determinar verdadeiro ou falso relativamente entre valores, você deve ter algo para compará-lo. Isto aplica-se a cadeias e valores numéricos, usando ==ou !=ou <, > >=, <=, etc.

Você pode atribuir um número inteiro a uma variável e, em seguida, obter verdadeiro ou falso com base nesse valor de variável.


1
A questão é se True == 1 é garantido pelo Python, não sobre o valor booleano de números inteiros.
Eric O Lebigot

-3

Basta escrever int(False)e você receberá 0, se você digitar, int(True)ele produzirá1


4
Isto significa apenas que os falsos e verdadeiros são entradas válidas para int(), com um significado numérico simples, não que eles são exatamente iguais a 0 e 1.
Eric O Lebigot

-5

Falso é um bool. Tem um tipo diferente. É um objeto diferente de 0, que é um número inteiro.

0 == Falseretorna True porque False é convertido em um número inteiro. int (False) retorna 0

A documentação python do operador == diz (help ('==')):

Os operadores <, >, ==, >=, <=, e !=comparar os valores de dois objetos. Os objetos não precisam ter o mesmo tipo. Se ambos são números, eles são convertidos em um tipo comum.

Como conseqüência, False é convertido em um número inteiro para a necessidade da comparação. Mas é diferente de 0.

>>> 0 is False
False

26
Isso não está certo: boolé uma subclasse de int, portanto, em um sentido muito real, um bool é um número inteiro. Por exemplo, isinstance(True, int)retorna True. E a verificação de igualdade não converte o booleano em int, pois nenhuma conversão é necessária: simplesmente chama int.__cmp__diretamente. Observe que bool.__cmp__ is int.__cmp__também é avaliado como True.
Mark Dickinson

3
-1 para esta resposta. Descrição incorreta do relacionamento entre bool e int (no Python 2). isinstance(True, int)=> Verdadeiro. Ou seja, True IS é um número inteiro e não requer conversão.
Página Inicial>

Eu tinha um script que retornava False ou Int ... usando while response is Falsefuncionado e while response == Falsenão ... Obrigado!
curly_brackets

5
Isso 0 is Falseé falso não diz nada. No seu intérprete interativo, digite x = -10, então y = -10, então x is ye isso também será falso. Só porque existem otimizações no local em que o intérprete Python reutiliza os mesmos objetos inteiros em determinadas circunstâncias (armazenar literais inteiros como constantes, inserir inteiros pequenos) não significa que isdeve ser usado quando você deseja testar a igualdade de valor inteiro .
Martijn Pieters
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.