Trilha de aprendizado · Nível 11 · Tutorial 1

Definir representações com __repr__ e __str__

Ao concluir, você poderá definir representações úteis de objetos para diagnóstico e apresentação, integrando suas classes a repr, str, print e f-strings.

  • Nível: Intermediário
  • Duração: 12 min
  • 7 passos
Definir representações com __repr__ e __str__

O que você vai percorrer

  1. Integrar a classe às operações de representação Entenda como o Python conecta repr e str aos métodos especiais definidos no tipo da classe. 1 min
  2. Construir uma representação para diagnóstico Crie um __repr__ que torne o tipo e o estado relevante de um objeto fáceis de inspecionar. 2 min
  3. Criar uma apresentação legível com __str__ Use __str__ para uma apresentação curta e compreensível, sem perder de vista a diferença para __repr__. 2 min
  4. Prever a exibição direta e dentro de listas Compare a representação de um dispositivo isolado com a representação dos mesmos objetos dentro de uma lista. 2 min
  5. Escolher a conversão nas f-strings Use !r e !s para controlar se uma f-string mostra a representação diagnóstica ou a apresentação legível de um objeto. 1 min
  6. Mostrar o necessário sem revelar segredos Escolha campos úteis para identificar um objeto sem transformar suas representações em exposição de dados sensíveis. 2 min
  7. Aplicar e verificar as duas representações Pratique uma implementação completa de __repr__ e __str__, execute verificações locais e confira qual representação aparece em cada contexto. 3 min

O que você vai aprender

  • Implementar __repr__ e __str__ com finalidades distintas e retornos textuais.
  • Prever qual representação será usada na exibição direta de um objeto e dentro de uma coleção.
  • Selecionar informações que ajudem a identificar o estado do objeto sem expor dados sensíveis.

Antes de começar

  • Criar objetos com classes e métodos de instância
  • Apresentar resultados com textos e f-strings

Passo 1 de 7

Integrar a classe às operações de representação

Entenda como o Python conecta repr e str aos métodos especiais definidos no tipo da classe.

Nomes reconhecidos pelo Python

Métodos especiais são contratos

Métodos especiais são pontos de integração reconhecidos pela linguagem. Quando você chama repr(objeto), o Python procura o comportamento associado a __repr__; quando chama str(objeto), procura o associado a __str__.

Não basta inventar um nome com sublinhados duplos. Um método chamado __mostrar__, por exemplo, é apenas um método comum: nenhuma operação nativa do Python o chamará automaticamente.

A operação consulta o tipo

As setas mostram a ideia central: a operação da linguagem consulta o método especial definido na classe — ou herdado por ela.

Diagrama mostrando repr(objeto) apontando para __repr__ na classe do objeto e str(objeto) apontando para __str__ na classe.

repr e str se conectam aos métodos especiais do tipo do objeto.

Defina o método na classe

Classe e instância não são equivalentes aqui

Compare as duas tentativas abaixo.

python
class Caixa:
    pass

caixa = Caixa()

# Isto cria apenas um atributo na instância.
caixa.__repr__ = lambda: "Caixa personalizada"

print(repr(caixa))  # Não usa o lambda acima.


class CaixaComRepr:
    def __repr__(self):
        return "Caixa personalizada"

outra_caixa = CaixaComRepr()
print(repr(outra_caixa))  # Usa __repr__ definido na classe.

Por que o primeiro caso não muda?

Em operações especiais como repr(objeto), o Python busca o método no tipo do objeto, considerando também métodos herdados. Por isso, adicionar __repr__ apenas a caixa não altera o resultado de repr(caixa).

É a mesma ideia geral que você já viu com __iter__ e __next__: nomes especiais funcionam porque o Python reconhece um contrato definido no tipo, não porque qualquer atributo da instância tenha esse nome.

Verifique a integração correta

Qual alteração personaliza repr(item)?

Considere item = Produto(). Qual alteração faz repr(item) usar uma representação personalizada?

Passo 2 de 7

Construir uma representação para diagnóstico

Crie um repr que torne o tipo e o estado relevante de um objeto fáceis de inspecionar.

Diagnóstico: tipo e estado visíveis

O papel de __repr__

Use __repr__ para criar uma representação voltada ao diagnóstico: ela deve ajudar você a reconhecer qual é o tipo do objeto e qual é seu estado relevante.

Para um dispositivo, uma forma útil inclui o nome da classe e campos identificáveis, como id, nome e estado. O formato pode lembrar a criação do objeto, mas não precisa recriá-lo nem servir como serialização.

Anatomia de uma representação diagnóstica

Cada parte da saída aponta para uma informação que facilita a inspeção do objeto.

Diagrama de uma representação de Dispositivo separada em nome da classe e pares de campo e valor: id, nome e estado.

Nome da classe + campos nomeados + valores explícitos tornam a saída pouco ambígua.

Implementando __repr__

Classe Dispositivo

Use repr() nos valores textuais. Assim, aspas, quebras de linha e outros caracteres especiais ficam explícitos na representação.

python
class Dispositivo:
    def __init__(self, identificador, nome, estado):
        self.identificador = identificador
        self.nome = nome
        self.estado = estado

    def __repr__(self):
        return (
            f"Dispositivo(identificador={self.identificador}, "
            f"nome={repr(self.nome)}, estado={repr(self.estado)})"

sensor = Dispositivo(42, "Sensor de temperatura", "ativo")
print(repr(sensor))
# Dispositivo(identificador=42, nome='Sensor de temperatura', estado='ativo')

Exemplo

Textos sem ambiguidade

Se nome fosse "Sensor\nexterno", usar repr(self.nome) mostraria 'Sensor\nexterno', com a quebra de linha visível como \n. Isso é mais útil para investigar o estado do que espalhar o texto em duas linhas.

O retorno é obrigatório

Atenção

Não basta imprimir

__repr__ precisa retornar uma str. Fazer apenas print(...) dentro do método produz uma saída lateral, mas o método termina retornando None. Ao usar repr(objeto), isso causa TypeError.

Também ocorre TypeError se você retornar, por exemplo, um número ou um dicionário.

Complete o contrato

O método __repr__ deve devolver um valor do tipo _.

Passo 3 de 7

Criar uma apresentação legível com __str__

Use str para uma apresentação curta e compreensível, sem perder de vista a diferença para repr.

Diagnóstico ou apresentação?

Uma visão para cada contexto

Você já usou __repr__ para identificar o tipo e o estado relevante de um objeto durante o diagnóstico. Use __str__ quando quiser uma apresentação curta e legível para quem verá o resultado.

Para um Dispositivo, __repr__ pode mostrar os campos nomeados; __str__ pode mostrar apenas nome e estado.

Duas representações, dois objetivos

A mesma instância pode ter uma saída detalhada para diagnóstico e outra resumida para apresentação.

Comparação visual entre um cartão detalhado de diagnóstico de um dispositivo, com identificador, nome e estado, e um cartão curto de apresentação mostrando somente nome e estado.

repr detalha o estado relevante; str prioriza leitura rápida.

Definindo __str__

Uma apresentação curta

Defina __str__ na classe e devolva uma string.

python
class Dispositivo:
    def __init__(self, identificador, nome, estado):
        self.identificador = identificador
        self.nome = nome
        self.estado = estado

    def __repr__(self):
        return (
            f"Dispositivo(identificador={self.identificador!r}, "
            f"nome={self.nome!r}, estado={self.estado!r})"
        )

    def __str__(self):
        return f"{self.nome} — {self.estado}"

sensor = Dispositivo("A17", "Sensor da entrada", "ativo")

print(str(sensor))
print(sensor)
# Sensor da entrada — ativo
# Sensor da entrada — ativo

Quem chama __str__?

str(sensor) chama sensor.__str__(). Para exibir diretamente um objeto, print(sensor) também usa __str__.

Assim como em __repr__, o método deve retornar uma str; apenas usar print() dentro dele não cumpre o contrato.

Atenção

Retorno inválido não tem alternativa

Se __str__ retornar, por exemplo, um número ou None, str(objeto) e print(objeto) geram TypeError. Python não troca automaticamente para __repr__ nesse caso.

Fallback: uma direção só

Quando __str__ não existe

Em uma classe simples que personaliza apenas __repr__, a implementação herdada de object.__str__ usa essa representação. Portanto, str(objeto) e print(objeto) mostram o resultado de __repr__.

Mas o contrário não acontece: criar somente __str__ não altera repr(objeto).

Associe a configuração ao comportamento

Relacione cada configuração da classe ao resultado esperado.

Toque em um item e depois no par correspondente.

Passo 4 de 7

Prever a exibição direta e dentro de listas

Compare a representação de um dispositivo isolado com a representação dos mesmos objetos dentro de uma lista.

Um objeto isolado

Três formas de observar o mesmo objeto

Considere que Dispositivo já define __repr__ para diagnóstico e __str__ para apresentação. No interpretador interativo padrão, escrever uma expressão como sensor faz o Python mostrar repr(sensor). Já print(sensor) usa str(sensor). Por isso, o mesmo objeto pode aparecer de formas diferentes conforme a operação.

Classe e observações no interpretador

python
class Dispositivo:
    def __init__(self, identificador, nome, estado):
        self.identificador = identificador
        self.nome = nome
        self.estado = estado

    def __repr__(self):
        return (
            f"Dispositivo(identificador={self.identificador!r}, "
            f"nome={self.nome!r}, estado={self.estado!r})"
        )

    def __str__(self):
        return f"{self.nome} — {self.estado}"

sensor = Dispositivo("D-01", "Sensor do laboratório", "ativo")

# No interpretador, avalie cada expressão separadamente:
sensor
print(sensor)
print(repr(sensor))

Qual operação escolhe cada representação?

O diagrama mostra a diferença entre avaliar diretamente o objeto no interpretador e usar chamadas explícitas.

Diagrama comparando um objeto Dispositivo isolado: a expressão direta sensor aponta para repr, print(sensor) aponta para str e print(repr(sensor)) imprime o texto produzido por repr.

Expressão direta no interpretador: repr. print(objeto): str. print(repr(objeto)): o texto diagnóstico de repr.

Quando o objeto entra em uma lista

A lista representa seus elementos com repr

Uma lista precisa formar uma representação de toda a sua estrutura. Para isso, ela usa repr em cada elemento. Assim, print(dispositivos) apresenta a lista e, dentro dela, aparecem as representações diagnósticas dos dispositivos — mesmo que cada um tenha __str__ personalizado.

Exemplo

Lista versus laço

outro = Dispositivo("D-02", "Sensor externo", "inativo")
dispositivos = [sensor, outro]

print(dispositivos)
# [Dispositivo(identificador='D-01', nome='Sensor do laboratório', estado='ativo'), Dispositivo(identificador='D-02', nome='Sensor externo', estado='inativo')]

for dispositivo in dispositivos:
    print(dispositivo)
# Sensor do laboratório — ativo
# Sensor externo — inativo

No primeiro print, o argumento é a lista; a lista usa repr para seus elementos. No laço, cada chamada recebe um Dispositivo isolado e usa str.

Dois fluxos de exibição

Compare o objeto entregue a print em cada caso.

Comparação lado a lado: print aplicado a uma lista contendo dois dispositivos produz detalhes por repr; um laço chama print para cada dispositivo individual e produz rótulos curtos por str.

print(lista) preserva a estrutura da lista; print(item) no laço apresenta cada item individualmente.

Preveja a saída

Associe cada expressão ao resultado

Use as regras vistas para associar cada expressão à saída correspondente.

Toque em um item e depois no par correspondente.

Explique a diferença

Uma lista não é um laço

Por que print(dispositivos) mostra a representação de diagnóstico dos elementos, enquanto o laço com print(dispositivo) mostra a apresentação curta?

Escreva pelo menos 40 caracteres (0/40).

Passo 5 de 7

Escolher a conversão nas f-strings

Use !r e !s para controlar se uma f-string mostra a representação diagnóstica ou a apresentação legível de um objeto.

Três formas de inserir o objeto

Conversão explícita na f-string

Em uma f-string, escolha a representação de acordo com quem lerá a mensagem:

  • {dispositivo!r} solicita repr(dispositivo): útil para diagnóstico.
  • {dispositivo!s} solicita str(dispositivo): útil para apresentação.
  • {dispositivo} também usa str(dispositivo) nesta classe, pois não há uma personalização de formatação.

Assim, !s torna sua intenção explícita; !r destaca que você quer inspecionar o estado do objeto.

Diagnóstico versus apresentação

A mesma instância pode gerar uma descrição detalhada ou uma mensagem curta, conforme a conversão escolhida.

Diagrama com um único objeto Dispositivo ao centro e três setas: uma para uma visão detalhada de campos de diagnóstico e duas para uma visão curta e legível para pessoas.

!r segue o caminho diagnóstico; !s e a ausência de conversão seguem o caminho de apresentação nesta classe.

Compare as saídas

Uma classe com as duas representações

Observe como !r, !s e a forma sem conversão usam o mesmo objeto.

python
class Dispositivo:
    def __init__(self, identificador, nome, estado):
        self.identificador = identificador
        self.nome = nome
        self.estado = estado

    def __repr__(self):
        return (
            f"Dispositivo(identificador={self.identificador!r}, "
            f"nome={self.nome!r}, estado={self.estado!r})"
        )

    def __str__(self):
        return f"{self.nome} — {self.estado}"


dispositivo = Dispositivo("DV-17", "Sensor da entrada", "ativo")

print(f"Diagnóstico: {dispositivo!r}")
print(f"Apresentação explícita: {dispositivo!s}")
print(f"Apresentação padrão: {dispositivo}")

Exemplo

Saída esperada

Diagnóstico: Dispositivo(identificador='DV-17', nome='Sensor da entrada', estado='ativo')
Apresentação explícita: Sensor da entrada — ativo
Apresentação padrão: Sensor da entrada — ativo

Em __repr__, !r aplicado aos atributos textuais deixa aspas e caracteres especiais explícitos de forma concisa. Já a mensagem de apresentação usa a forma curta definida por __str__.

Dica

Escolha pelo destinatário

Use !r em mensagens para investigar objetos durante o desenvolvimento. Use !s — ou nenhuma conversão, quando a intenção estiver clara — em mensagens voltadas a pessoas usuárias.

Escolha a conversão adequada

Mensagem para suporte

Considere que dispositivo é a instância do exemplo. Qual f-string é mais adequada para registrar uma mensagem de diagnóstico destinada ao suporte técnico?

Mensagem de apresentação

Complete a f-string para mostrar a apresentação legível do objeto de forma explícita:

f"Status atual: {dispositivo___}"

Passo 6 de 7

Mostrar o necessário sem revelar segredos

Escolha campos úteis para identificar um objeto sem transformar suas representações em exposição de dados sensíveis.

Representações não são um canal privado

Diagnóstico com critério

__repr__ deve ajudar você a reconhecer o tipo e o estado relevante do objeto, mas não precisa mostrar todos os seus atributos. Uma representação pode aparecer em listas, no depurador e em mensagens de diagnóstico; portanto, trate seu conteúdo como potencialmente visível.

O que mostrar e o que ocultar

Diagrama de um dispositivo com identificador e estado destacados como informações úteis, e um token de acesso ocultado por uma faixa de censura.

Inclua dados que identificam o estado do objeto; omita segredos, como tokens de acesso.

Atenção

Não revele parte do segredo

Evite exibir o token inteiro, seus primeiros caracteres ou seus últimos caracteres. Se precisar sinalizar sua existência, use um marcador fixo, como token=<oculto>, que não derive nenhum trecho do valor real.

Uma classe que preserva o token

Representações deliberadas

O token existe no objeto, mas não participa das saídas públicas.

python
class Dispositivo:
    def __init__(self, identificador, nome, estado, token_acesso):
        self.identificador = identificador
        self.nome = nome
        self.estado = estado
        self.token_acesso = token_acesso

    def __repr__(self):
        return (
            f"Dispositivo(identificador={self.identificador!r}, "
            f"nome={self.nome!r}, estado={self.estado!r})"
        )

    def __str__(self):
        return f"{self.nome} — {self.estado}"

sensor = Dispositivo(
    "A17",
    "Sensor da recepção",
    "online",
    "tok_ficticio_9X2"
)

print(repr(sensor))
print(sensor)
print([sensor])

Exemplo

Saídas esperadas

Dispositivo(identificador='A17', nome='Sensor da recepção', estado='online')
Sensor da recepção — online
[Dispositivo(identificador='A17', nome='Sensor da recepção', estado='online')]

O token_acesso continua armazenado, porém não aparece nem no diagnóstico nem na apresentação. O formato parecido com uma construção é útil apenas enquanto não compromete segurança e clareza.

Avalie uma representação

Token em uma lista

Se __repr__ incluir token_acesso, o token poderá aparecer ao executar print([sensor]).

Reescreva com segurança

Diagnóstico sem exposição

Esta implementação é excessiva:

def __repr__(self):
    return f"Dispositivo(id={self.identificador!r}, estado={self.estado!r}, token={self.token_acesso!r})"

Escreva uma linha de return para __repr__ que mantenha informações úteis de diagnóstico, mas não revele o token.

Escreva pelo menos 40 caracteres (0/40).

Dica

Critério de escolha

Antes de incluir um campo, pergunte: ele ajuda a identificar o objeto ou investigar seu estado? Se sim, inclua-o. Se for sensível e não for indispensável, omita-o ou use um marcador fixo.

Passo 7 de 7

Aplicar e verificar as duas representações

Pratique uma implementação completa de repr e str, execute verificações locais e confira qual representação aparece em cada contexto.

Prática local: complete a classe

Objetivo da prática

No seu editor, crie um arquivo Python e complete os dois métodos abaixo. Use dados fictícios: o token existe no objeto, mas não deve aparecer em nenhuma saída. Depois execute o arquivo no seu próprio computador.

Critérios:

  • __repr__ deve identificar o tipo e mostrar identificador, nome e estado;
  • __str__ deve produzir uma mensagem curta com nome e estado;
  • ambos devem retornar uma str, e não usar print dentro do método.

Código inicial e verificações

Substitua os dois retornos temporários antes de executar.

python
class Dispositivo:
    def __init__(self, identificador, nome, estado, token_acesso):
        self.identificador = identificador
        self.nome = nome
        self.estado = estado
        self.token_acesso = token_acesso

    def __repr__(self):
        # Retorne uma str diagnóstica. Use !r para os textos.
        return ""

    def __str__(self):
        # Retorne uma str curta para apresentação.
        return ""


central = Dispositivo(101, "Sensor da entrada", "ativo", "tok_ficticio_9x")
reserva = Dispositivo(102, "Sensor do depósito", "em espera", "tok_ficticio_2k")

dispositivos = [central, reserva]

print("repr:", repr(central))
print("str:", str(central))
print("print:", central)
print("lista:", dispositivos)
print(f"Diagnóstico: {central!r}")
print(f"Painel: {central!s}")

Compare os contextos de exibição

Resultado de referência

Após completar a classe, suas saídas podem seguir este formato:

repr: Dispositivo(identificador=101, nome='Sensor da entrada', estado='ativo')
str: Sensor da entrada (ativo)
print: Sensor da entrada (ativo)
lista: [Dispositivo(identificador=101, nome='Sensor da entrada', estado='ativo'), Dispositivo(identificador=102, nome='Sensor do depósito', estado='em espera')]
Diagnóstico: Dispositivo(identificador=101, nome='Sensor da entrada', estado='ativo')
Painel: Sensor da entrada (ativo)

O nome da classe pode ser escrito diretamente como Dispositivo ou obtido por type(self).__name__. O essencial é manter a finalidade: diagnóstico em __repr__ e apresentação em __str__.

O caminho de cada representação

Observe como o mesmo objeto é convertido de modo diferente conforme o contexto.

Diagrama com um objeto Dispositivo no centro e setas para uma visão detalhada de diagnóstico, uma visão curta de apresentação, uma lista que usa a visão detalhada para cada elemento e duas f-strings, uma diagnóstica e uma de painel.

repr, listas e !r usam a visão diagnóstica; str, print(objeto) e !s usam a apresentação.

Dica

Conferência de segurança

Procure pelo valor tok_ficticio_9x nas saídas do terminal. Ele não deve aparecer. Não mostre apenas parte do token: omita-o por completo das duas representações.

Relate o que você observou

Explique suas verificações

Depois de executar seu arquivo, relate: qual forma apareceu em print(central); qual apareceu na lista; a diferença entre !r e !s; e como você confirmou que o token não vazou.

Escreva pelo menos 180 caracteres (0/180).

Síntese e conclusão

Resumo

Critérios para representações úteis

Use estas decisões ao criar representações de outras classes.

  • Implemente __repr__ para diagnóstico: inclua tipo e estado relevante de forma clara.
  • Implemente __str__ para apresentação: prefira uma mensagem curta e adequada ao contexto.
  • Os dois métodos devem retornar uma str; imprimir dentro deles não cumpre o contrato.
  • Na ausência de um __str__ personalizado, a apresentação recorre a __repr__; o contrário não ocorre.
  • Uma lista representa seus elementos com repr, enquanto imprimir cada objeto individualmente usa str.
  • Use !r para uma mensagem diagnóstica e !s para uma mensagem de apresentação.
  • Selecione campos úteis e omita segredos, pois repr pode circular em listas, depuradores e logs.

Tutorial concluído

Parabéns! Você concluiu: Definir representações com __repr__ e __str__

Muito bem! Você já pode definir __repr__ e __str__ com propósitos distintos, prever as saídas em listas e f-strings e evitar a exposição de dados sensíveis.

Baixe o Aplicativo agora para ter acesso a + de 5000 cursos gratuitos, exercícios, certificado e muito conteúdo sem pagar nada!

  • Cursos online 100% gratuitos do início ao fim

    Milhares de cursos online em vídeo, ebooks e áudiobooks.

  • Mais de 60 mil exercícios gratuitos

    Para testar seus conhecimentos no decorrer dos cursos online

  • Certificado Digital gratuito válido em todo o Brasil

    Gerado diretamente na galeria de fotos do seu celular e enviado ao seu e-mail

Aplicativo Cursa na tela de ebook, na tela de curso em vídeo e na tela de exercícios do curso, mais o certificado de conclusão de curso