Decisões e Seleção

Valores booleanos e expressões booleanas

O tipo em Python para armazenar os valores verdadeiro e falso é chamado de bool, em homenagem ao matemático britânico George Boole. George Boole criou a Álgebra Booleana, que é a base de toda a aritmética computacional moderna.

Existem apenas dois valores booleanos. Eles são True e False. As iniciais maiúsculas são importantes, uma vez que true e false não são valores booleanos (lembre-se de que maiúsculas e minúsculas fazem diferença para o Python).

Note

Valores booleanos não são strings!

É extremamente importante perceber que True e False não são strings. Eles não estão entre aspas. Eles são somente dois valores do tipo de dados bool. Olhe atentamente os tipos mostrados abaixo.

Uma expressão booleana é uma expressão que resulta em um valor booleano. O operador de igualdade, ==, compara dois valores e produz um valor booleano correspondente aos dois valores serem ou não iguais entre si.

No primeiro comando, os dois operandos são iguais, de forma que a expressão tem valor True. No segundo comando, 5 não é igual a 6, de forma que obtemos False.

O operador == é um dos seis operadores de comparação comuns; os outros são:

x != y               # x não é igual a y
x > y                # x é maior do que y
x < y                # x é menor do que y
x >= y               # x é maior ou igual a y
x <= y               # x é menor ou igual a y

Embora essas operações sejam provavelmente familiares a você, os símbolos em Python são diferentes dos símbolos matemáticos. Um erro comum é usar somente um símbolo de igual (=) em vez de dois sinais iguais (==). Lembre-se de que = é um operador de atribuição e o == é um operador de comparação. Também, os operadores =< ou => não existem.

Note também que um teste de igualdade é simétrico, mas atribuição não é. Por exemplo, se a == 7 então 7 == a. Mas, em Python, a expressão a = 7 é válida e 7 = a não é. (Você pode explicar por que?)

Rascunho

Teste seu entendimento

    Q-6: Quais das seguintes é uma expressão booleana? Selecione todos que são.

  • True
  • True e False são ambas literais booleanas.
  • 3 == 4
  • A comparação entre dois números usando == resulta em True ou False (neste caso False), ambos valores booleanos.
  • 3 + 4
  • 3+4 resulta em 7, que é um número, não um valor booleano.
  • 3 + 4 == 7
  • 3+4 resulta em 7. 7 == 7 então resulta em True, que é um valor booleano.
  • "False"
  • Entre aspas, False é interpretado como um string, não como um valor booleano. Se as aspas não fossem incluídas, False sozinho seria de fato um valor booleano

Operadores lógicos

Existem três operadores lógicos: and, or e not. A semântica (significado) desses operadores é similar ao significado deles em português. Por exemplo, x > 0 and x < 10 é verdadeiro somente se x é maior do que 0 e ao mesmo tempo, x é menor do que 10. Como você descreveria isso em palavras? Você diria que x está entre 0 e 10, não incluindo as extremidades.

n % 2 == 0 or n % 3 == 0 é verdadeiro se uma das condições é verdadeira, isto é, se o número é divisível por 2 ou divisível por 3. Neste caso, uma, ou a outra, ou ambos as partes tem que ser verdadeira para o resultado ser verdadeiro.

Finalmente, o operador not nega uma expressão booleana, de forma que not  x > y é verdadeiro se x > y é falso, isto é, se x é menor ou igual a y.

Erro comum!

Existe um erro muito comum que ocorre quando programadores tentam escrever expressões booleanas. Por exemplo, suponha que queremos verificar se uma variável número tem valor 5, 6, or 7. Em palavras, podemos dizer: “número é igual a 5 ou 6 ou 7”. Entretanto, se traduzimos isto em Python, número == 5 or 6 or 7, isso não será correto. O operador or precisa juntar a verificação das três igualdades. A forma correta de escrever isto é número == 5 or número == 6 or número == 7. Isto pode parecer como um monte de digitação mas é absolutamente necessário. Não dá para fazer de forma mais compacta.

Rascunho

Teste seu entendimento

    Q-9: Qual é a expressão correta em Python para verificar se um número armazenado na variável x está entre 0 e 5.

  • x > 0 and < 5
  • Cada comparação deve ser exatamente entre dois valores. Neste caso, na comparação da direita falta um valor do lado esquerdo da expressão < 5.
  • 0 < x < 5
  • Esta é sutil. Embora a maior parte das linguagens de programação não permite esta sintaxe, em Python, esta sintaxe é permitida. Entretanto, você não deveria usá-la. Em vez disso, faça comparações múltiplas usando and ou or.
  • x > 0 or x < 5
  • Embora esta sintaxe seja legal em Python,a expressão está incorreta. Ela terá valor verdadeiro para todos os números que são ou maiores do que zero ou menores do que 5. Como todos os números são ou maiores do que zero ou menores do que 5, esta expressão será sempre verdadeira.
  • x > 0 and x < 5
  • Sim, com o operador and ambas as expressões devem ser verdadeiras de forma que para a expressão ser verdadeira, o número deve ser maior do que 0 e menor do que 5.

Precedência de operadores

Adicionamos um certo número de operadores àqueles que aprendemos nos capítulos anteriores. É importante entender como os operadores se relacionam entre si em relação à precedência. Python sempre usará os operadores aritméticos primeiro (exponenciação primeiro, depois multiplicação/divisão e depois adição/subtração). Depois vêm os operadores relacionais. Finalmente, os operadores lógicos vêm por último. Isto quer dizer que o valor da expressão x*5 >= 10 and y-6 <= 20 será determinado de forma que as operações aritméticas são feitas e depois as relações. O and será deixado por último. Embora muitos programadores poderiam colocar parênteses nas expressões relacionais, isto não é necessário.

A tabela seguinte resume a precedência dos operadores em Python do maior ao menor. A tabela completa da linguagem pode ser encontrada em Python Documentation.

Nível

Categoria

Operadores

7(alto)

exponenciação

**

6

multiplicação

*,/,//,%

5

adição

+,-

4

relacional

==,!=,<=,>=,>,<

3

lógico

not

2

lógico

and

1(baixo)

lógico

or

Rascunho

Teste seu entendimento

    Q-11: Quais das seguintes expressões corresponde, usando parênteses, à seguinte expressão: 5*3 > 10 and 4+6==11

  • ((5*3) > 10) and ((4+6) == 11)
  • Sim, * e + têm as maiores precedências, seguidos por > e == e então o operador "and"
  • (5*(3 > 10)) and (4 + (6 == 11))
  • Operadores aritméticos (*, +) têm maior precedência do que os operadores de comparação (>, ==)
  • ((((5*3) > 10) and 4)+6) == 11
  • Este agrupamento assume que Python simplesmente prioriza da esquerda para a direita, o que é incorreto. O agrupamento correto segue a precedência listada na tabela nesta seção.
  • ((5*3) > (10 and (4+6))) == 11
  • Este agrupamento assume que "and" tem uma precedência maior que que ==, o que não é verdadeiro.

Execução condicional: seleção binária

Com a finalidade de escrever programas úteis, quase sempre temos a necessidade de verificar condições e alterar o comportamento do programa de acordo com os resultados das condições. Comandos de seleção, algumas vezes também denominados de comandos condicionais nos dá essa habilidade. A forma mais simples de seleção é o comando if. Ele é algumas vezes denominado de seleção binária uma vez que admite dois possíveis caminhos de execução.

A sintaxe de um comando if se parece com:

if EXPRESSÃO BOOLEANA:
    COMANDOS_1        # executados se condição tem valor True
else:
    COMANDOS_2        # executados se condição tem valor False

A expressão booleana depois do if é chamada de condição. Se é verdadeira, então os comandos tabulados (COMANDOS_1) são executados. Se não, então os comandos tabulados depois do else são executados.

Assim como a definição de função do último capítulo e outros comandos compostos como for, o comando if consiste de uma linha de cabeçalho e um corpo. A linha de cabeçalho começa com a palavra if seguida por uma expressão booleana e termina com dois pontos (:).

Os comandos tabulados que seguem é chamado de bloco. O primeiro comando com tabulação diferente marca o fim do bloco.

Cada comando dentro do primeiro bloco de comandos é executado em ordem se a expressão booleana tem valor True. Todo o primeiro bloco de comandos é pulado se a expressão booleana tem valor False e todos os comandos sob o else são executados.

Não há limite no número de comandos que podem aparecer nos dois blocos de um comando if, mas tem que haver pelo menos um comando em cada bloco.

Lab

Rascunho

Teste seu entendimento

    Q-15: Quantos comandos podem aparecer em cada bloco (o do if e o do else) em um comando condicional?

  • Exatamente um.
  • Cada bloco pode também conter mais do que um.
  • Zero ou mais.
  • Cada bloco deve conter pelo menos um comando.
  • Um ou mais.
  • Sim, um bloco deve conter pelo menos um comando e pode ter vários comandos.
  • Um ou mais e cada um precisa conter o mesmo número.
  • Os blocos podem conter números diferentes de comandos.

    Q-16: O que o seguinte código imprime (escolha entre as saídas a, b, c ou nada).

    if (4 + 5 == 10):
        print("VERDADEIRO")
    else:
        print("FALSO")
    

    Saída a

    VERDADEIRO
    

    Saída b

    FALSO
    

    Saída c

    VERDADEIRO
    FALSO
    
  • Saída a

  • VERDADEIRO é impresso pelo bloco do if, o qual é executado somente se o condicional (neste caso, 4+5 == 10) é verdadeiro. Neste caso, 5+4 não é igual a 10.

  • Saída b

  • Como 4+5==10 tem valor False, o Python pulará o bloco do if e executará o comando do bloco do else.

  • Saída c

  • o Python nunca imprimirá ambos VERDADEIRO e FALSO porque ele executará ou o bloco do if ou o bloco do else, mas nunca ambos.

  • Nada será impresso

  • o Python sempre executará ou o bloco do if (se a condição é verdadeira) ou o bloco do else (se a condição é falsa). Ele nunca pulará os dois blocos.

    Q-17: O que o seguinte código imprime?

    if (4 + 5 == 10):
        print("VERDADEIRO")
    else:
        print("FALSO")
    print("VERDADEIRO")
    

    Saída a

    VERDADEIRO
    

    Saída b

    VERDADEIRO
    FALSO
    

    Saída c

    FALSO
    VERDADEIRO
    

    Saída d

    VERDADEIRO
    FALSO
    VERDADEIRO
    
  • Saída a

  • Embora VERDADEIRO seja impresso depois que o comando if-else termina, cada bloco dentro do comando if-else imprime algo também. Neste caso, o Python teria que ter pulado ambos os blocos do comando if-else, o que ele nunca faria.

  • Saída b

  • Como há um VERDADEIRO impresso depois que o comando if-else termina, o Python sempre imprimirá VERDADEIRO por último.

  • Saída c

  • o Python imprimirá FALSO dentro do bloco do else (porque 5+4 não é igual a 10), e então imprimirá VERDADEIRO depois de completar o comando if-else.

  • Saída d

  • Para imprimir estas três linhas, Python teria que executar ambos os blocos do comando if-else, o que ele nunca fará.

Seleção unária: omissão do else

Outra forma do comando if é um no qual o else é totalmente omitido. Isso cria um mecanismo chamado seleção unária. Neste caso, quando a condição tem valor True, os comando são executados. Caso contrário, o fluxo de execução continua no comando depois do if.

O que é impresso quando o valor de `` x`` é negativo? Tente isso.

Rascunho

Teste seu entendimento

    Q-21: O que o seguinte código imprime?

    x = -10
    if x < 0:
        print("O número negativo ",  x, " não é válido aqui.")
    print("Isto é sempre impresso.")
    

    Saída a

    Isto é sempre impresso.
    

    Saída b

    O número negativo -10 não é válido aqui.
    Isto é sempre impresso.
    

    Saída c

    O número negativo -10 não é válido aqui.
    
  • Saída a

  • Porque -10 é menor do que 0, Python executará o corpo do comando if aqui.

  • Saída b

  • Python executa o corpo do bloco do if bem como o comando que segue o bloco do if.

  • Saída c

  • Python executará o comando que segue o bloco if (porque ele está no bloco do else, mas como um comando normal).

  • Causará um erro porque todo if deve ter um else.

  • É válido ter um bloco do if sem um bloco do else correspondente (embora você não possa ter um bloco do else sem um bloco do if correspondente).

    Q-22: O seguinte código causará um erro?

    x = -10
    if x < 0:
        print("O número negativo ",  x, " não é válido aqui.")
    else:
        print(x, " é um número positivo.")
    else:
        print("Isto é sempre impresso.")
    
  • Não

  • Cada bloco de else precisa ter exatamente um bloco de if correspondente. Se você quer encadear comandos if-else juntos, você precisa usar a construção else, descrita na seção 6.7.

  • Sim

  • Isto causará um erro porque o segundo bloco de else não está relacionado com nenhum bloco de if.

Condicionais aninhados

Um condicional pode também ser aninhado dentro de outro. Por exemplo, assuma que temos duas variáveis inteiras x e y. O seguinte padrão de seleção mostra como podemos decidir como eles são relacionados entre si.

if x < y:
    print("x e' menor do que y.")
else:
    if x > y:
        print("x e' maior do que y.")
    else:
        print("x e y devem ser iguais.")

O condicional externo tem duas ramificações. A segunda ramificação (o else externo) contém outro comando if, o qual tem outras duas ramificações. Aquelas duas ramificações podem também conter comandos condicionais.

O fluxo de controle pode ser visto nesta ilustração do fluxograma.

../_images/fluxograma_condicional_aninhado.png

Abaixo você encontra um programa completo que define valores para x and y. Execute o programa e veja o resultado. Então mude os valores das variáveis para mudar o fluxo de controle.

Note

Em algumas linguagens de programação, encontrar o if correspondente a um else pode ser um problema. Entretanto, em Python isto não é o caso. O padrão de tabulação nos diz exatamente qual else corresponde a qual if.

Se você está ainda inseguro, aqui vai a mesma seleção do exemplo codelens. Simule passo-a-passo para ver como o print correto é escolhido.

CodeLens: (sel1)

Rascunho

Teste seu entendimento

    Q-26: O seguinte código causará um erro?

    x = -10
    if x < 0:
        print("O número negativo ",  x, " não é válido aqui.")
    else:
        if x > 0:
            print(x, " é um número positivo.")
        else:
            print(x," é 0.")
    
  • Não

  • Este é um comando if-else aninhado legítimo. O comando if-else interno está completamente contido no corpo do bloco do else externo.

  • Sim

  • Este é um comando if-else aninhado legítimo. O comando if-else interno está completamente contido no corpo do bloco do else externo.

Condicionais encadeados

Python provê uma forma alternativa de escrever seleções aninhadas como as mostradas na seção anterior. Isto é chamado algumas vezes como condicionais encadeadas

if x < y:
    print("x e' menor do que y.")
elif x > y:
    print("x e' maior do que y.")
else:
    print("x e y devem ser iguais.")

O fluxo de controle pode ser desenhado com uma orientação diferente mas o padrão resultante é idêntico ao mostrado acima.

../_images/fluxograma_condicional_encadeado.png

elif é uma abreviação de else if. Novamente, exatamente uma ramificação será executada. Não há limites no número de elif mas apenas um simples (e opcional) else final é permitido e precisa ser a última ramificação do comando.

Cada condição é verificada em ordem. Se a primeira é falsa, a próxima é então verificada , e assim por dianta. Se uma delas é verdadeira, a ramificação correspondente é executada e o comando termina. Mesmo que mais do que uma condição seja verdadeira, apenas a ramificação da primeira verdadeira é executada.

Aqui vai o mesmo programa usando elif.

Rascunho

Teste seu entendimento

    Q-29: Quais dentre I, II e III abaixo dá o mesmo resultado que o seguinte if aninhado?

    # comando if-else aninhado
    x = -10
    if x < 0:
        print("O número negativo ",  x, " não é válido aqui.")
    else:
        if x > 0:
            print(x, " é um número positivo.")
        else:
            print(x, " é 0.")
    
    1. if x < 0:
          print("O número negativo ",  x, " não é válido aqui.")
      else (x > 0):
          print(x, " é um número positivo.")
      else:
          print(x, " é 0.")
      
    2. if x < 0:
          print("O número negativo ",  x, " não é válido aqui.")
      elif (x > 0):
          print(x, " é um número positivo.")
      else:
          print(x, " é 0.")
      
    3. if x < 0:
          print("O número negativo ",  x, " não é válido aqui.")
      if (x > 0):
          print(x, " é um número positivo.")
      else:
          print(x, " é 0.")
      
  • I somente

  • Você não pode usar uma expressão booleana depois de um else.

  • II somente

  • Sim, II dará o mesmo resultado.

  • III somente

  • Não, III não dará o mesmo resultado. O primeiro comando if será verdadeiro, mas o segundo será falso, de forma que os comandos do bloco do else serão executados.

  • II e III

  • Não, embora II seja correta, III não dará o mesmo resultado. Teste isso.

  • I, II e III

  • Não, em I você não pode ter uma expressão booleana depois de um else.

    Q-30: O que o seguinte código imprimirá se x = 3, y = 5 e z = 2?

    if x < y and x < z:
        print ("a")
    elif y < x and y < z:
        print ("b")
    else:
        print ("c")
    
  • a

  • Enquanto o valor de x é menor do que o valor de y (3 é menor do que 5) ele não é menor do que o valor de z (3 não é menor do que 2).

  • b

  • O valor de y não é menor do que o valor de x (5 não é menor do que 3).

  • c

  • Como as duas primeiras expressões booleanas são falsas, o else será executado.

Funções booleanas

Funções podem retornar valores booleanos, o que é frequentemente conveniente para esconder dentro de funções testes complidados. Por exemplo:

O nome desta função é eDivisivel. É comum dar nomes a funções booleanas que lembrem questões sim/não. eDivisivel retorna ou True ou False para indicar se x é ou não divisível por y.

Podemos fazer a função mais compacta tirando vantagem do fato que a condição do comando if é ele próprio uma expressão booleana. Podemos retorná-lo diretamente, evitando todo o comando if:

def eDivisivel(x, y):
    return x % y == 0

Funções booleanas são usadas frequentemente em comandos condicionais:

if eDivisivel(x, y):
    ... # faça alguma coisa ...
else:
    ... # faça outra coisa ...

Pode ser tentador escrever algo como if eDivisivel(x, y) == True: mas a comparação extra não é necessária. O seguinte exemplo mostra uma aplicação da função eDivisivel. Teste isto com uns alguns outros argumentos para ver o que é impresso.

Abaixo você encontra mesmo programa em codelens.

CodeLens: (ch06_boolcodelens)

Rascunho

Teste seu entendimento

    Q-35: O que é uma função booleana?

  • Uma função que retorna True ou False
  • Uma função booleana é como outra função qualquer, mas ela sempre retorna True ou False.
  • Uma função que usa True ou False como argument
  • Uma função booleana pode ter qualquer número de argumentos (incluindo 0, embora seja raro), de qualquer tipo.
  • O mesmo que uma expressão booleana
  • Uma expressão booleana é um comando com valor True ou False, e.g. 5+3==8. Uma função é uma série de comandos agrupados com um nome que somente são executados quando você chama a função.

    Q-36: O seguinte comando é legal em Python (assumindo que x, y e z são definidos como números)?

    return x + y < z
    
  • Sim

  • É perfeitamente válido retornar o resultado calculado por uma expressão booleana.

  • Não

  • x + y < z é uma expressão booleana válida, a qual terá valor True ou False. É perfeitamente legal uma função retornar True ou False e ter uma expressão calculada na mesma linha do return.

Glossário

aninhamento

Uma estrutura de programa dentro de outra, tal como um comando condicional dentro de uma ramificação de um outro comando condicional.

bloco

Um grupo de comandos consecutivos com a mesma tabulação.

comando condicional

Um comando que controla o fluxo de execução dependendo de alguma condição. Em Python, if, elif e else são usados para comandos condicionais.

condição

Uma expressão booleana em um comando condicional que determina a ramificação a ser executada.

condicional encadeada

Uma ramificação condicional com mais do que dois fluxos de execução possíveis. Em Python, condicionais encadeadas são escritas com comandos if ... elif ... else.

corpo

Um bloco de comandos em um comando composto que segue o cabeçalho.

expressão booleana

Uma expressão que é ou verdadeira ou falsa.

função booleana

Uma função que retorna um valor booleano. O valores possíveis do tipo bool são False e True.

operador de comparação

Um dos operadores que compara dois valores: ==, !=, >, <, >=, and <=.

operador lógico

Um dos operadores que combinam expressões booleanas: and, or e not.

operador módulo

Um operador, denotado por um sinal de porcentagem ( %), que calcula o resto da divisão de um número por outro, considerando que o valor da divisão é um número inteiro.

ramificação

Um dos possíveis caminhos do fluxo de execução determinado por uma execução condicional.

valor booleano

Existem exatamente dois valores booleanos: True e False. Valores booleanos são resultados de cálculos de expressões booleanas. Eles são do tipo bool.

Exercicíos

  1. Qual o valor de cada uma das expressões?

    1. 3 == 3

    2. 3 != 3

    3. 3 >= 4

    4. not (3 < 4)

  2. Descreva os opostos lógicos de cada uma das condições. Não é permitido usar o operador not.

    1. a > b

    2. a >= b

    3. a >= 18  and  dia == 3

    4. a >= 18  and  dia != 3

  3. Escreva uma função que, dada uma nota, retorna um string — o grau da nota de acordo com o esquema:

    Nota

    Grau

    >= 90

    A

    [80-90)

    B

    [70-80)

    C

    [60-70)

    D

    < 60

    F

    Os colchetes e os parênteses denotam intervalos fechados e abertos. Um intervalo fechado inclui o número enquanto um intervalo aberto o exclui. Logo, 79.99999 corresponde a grau C, mas 80 corresponde a grau B.

    Seja xs = [83, 75, 74.9, 70, 69.9, 65, 60, 59.9, 55, 50, 49.9, 45, 44.9, 40, 39.9, 2, 0]

    Teste sua função imprimindo o grau para cada elemento da lista.

  4. Modifique o programa de diagrama de barras da tartaruga para que as barras, para qualquer valor de 200 ou mais, sejam preenchida com vermelho; para valores entre [100 e 200) sejam preenchidas com amarelo e barras representando valores menores do que 100 sejam preenchidas com verde.

  5. No programa do diagrama de barras da tartaruga, o que você espera acontecer se um ou mais dos valores dados na lista é negativo? Teste isto. Mude o programa de forma que quando ele imprime um texto para barras negativas, esse texto apareça embaixo da barra.

  6. Escreva uma função acheHipot que, dados os comprimento de dois lados de um triângulo retângulo, retorna o comprimento da hipotenusa. (Dica: o valor de x ** 0.5 é a raiz quadrada, ou use sqrt do módulo matemático)

  7. Escreva uma função chamada é_par(n) que recebe como argumento um inteiro e retorna True se o argumento é um número par e False se ele é ímpar.

  8. Agora escreva a função é_ímpar(n) que retorna True quando n é ímpar e False caso contrário.

  9. Modifique é_ímpar de forma que ela use uma chamada para é_par para determinar se o argumento é um inteiro par ou ímpar.

  10. Escreva uma função é_ânguloreto que, dado o comprimento de três lados de um triângulo, determina se o triângulo é retângulo. Asssuma que o terceiro argumento é sempre o lado maior. Ela retorna True se é um triângulo retângulo, ou False caso contrário.

    Dica: aritimética de ponto flutuante não é sempre exatamente precisa, de forma que não é seguro testar números em ponto flutuante para igualdade. Se um bom programador deseja saber se x é igual ou suficientemente perto de y, ele provavelmente usaria em seu código

    if  abs(x-y) < 0.000001:      # se x é aproximadamente igual a  y
        ...
    
  11. Estenda o programa acima de forma que os lados possam ser dados à função em qualquer ordem.

  12. Um ano é bissexto se ele é divisível por 4 a menos que seja um século que não é divisível por 400. Escreva uma função que receba um ano como argumento e retorna True se o ano é bissexto e False caso contrário.

  13. Implemente o programa da data da Páscoa descrito em classe.

Rascunho

You have attempted of activities on this page