Médio Python

Verificação segura com isinstance e None

Enunciado

Escreva uma função descrever(valor) que retorne uma string descrevendo o valor recebido. Se for None, retorne "sem valor". Se for bool, retorne "booleano". Se for int ou float, retorne "número". Se for str, retorne "texto". Para qualquer outro tipo, retorne "desconhecido". Imprima o resultado para os valores None, True, 3, 2.5, "oi" e [1, 2].

Requisitos

  • Usar isinstance para checar os tipos.
  • Tratar bool antes de int, pois bool é subclasse de int.
  • Comparar com None usando is.
  • Imprimir uma linha por valor testado.

Código inicial

def descrever(valor):
    # complete aqui
    pass

for v in [None, True, 3, 2.5, "oi", [1, 2]]:
    print(descrever(v))

Saída esperada

sem valor
booleano
número
número
texto
desconhecido
Ver dica

A ordem dos if importa: True também é int, então verifique bool primeiro.

Mostrar solução
def descrever(valor):
    # None é comparado com is, não com ==.
    if valor is None:
        return "sem valor"
    # bool precisa vir antes de int: bool é subclasse de int.
    if isinstance(valor, bool):
        return "booleano"
    if isinstance(valor, (int, float)):
        return "número"
    if isinstance(valor, str):
        return "texto"
    return "desconhecido"

for v in [None, True, 3, 2.5, "oi", [1, 2]]:
    print(descrever(v))

Passo a passo

  1. A função recebe valor e o primeiro teste é valor is None, que captura o caso especial.
  2. Em seguida checamos isinstance(valor, bool): como True é instância de bool e também de int, essa ordem evita classificá-lo como número.
  3. isinstance(valor, (int, float)) aceita uma tupla de tipos, cobrindo inteiros e floats de uma vez.
  4. isinstance(valor, str) trata textos.
  5. Qualquer outro tipo cai no return "desconhecido".
  6. O laço percorre a lista e imprime o resultado de cada chamada.

Por que funciona

isinstance respeita a hierarquia de classes, então precisamos ordenar as verificações do mais específico para o mais genérico. Usar is None é idiomático e imune a classes que sobrescrevem __eq__. A função não altera o valor recebido, apenas inspeciona seu tipo em tempo de execução.

Erros comuns

  • Colocar isinstance(valor, int) antes de bool: True seria classificado como "número". Corrija invertendo a ordem.
  • Usar valor == None: funciona, mas is None é o padrão recomendado.
  • Esquecer o return "desconhecido": a função devolveria None para listas, imprimindo None em vez de "desconhecido".

Outra forma de resolver

Usando um dicionário de tipos:

def descrever(valor):
    if valor is None:
        return "sem valor"
    if isinstance(valor, bool):
        return "booleano"
    mapa = {int: "número", float: "número", str: "texto"}
    return mapa.get(type(valor), "desconhecido")

É preferível quando há muitos tipos, mas perde subclasses (por isso bool continua tratado antes).

Saída esperada

sem valor
booleano
número
número
texto
desconhecido