Trilha de aprendizado · Nível 11 · Tutorial 7

Definir métodos de classe e métodos estáticos

Ao concluir, você poderá definir construtores alternativos e operações associadas a um tipo, escolhendo corretamente entre classmethod, staticmethod e funções de módulo.

  • Nível: Intermediário
  • Duração: 15 min
  • 6 passos
Definir métodos de classe e métodos estáticos

Passo 1 de 6

Receber a classe com @classmethod

Use @classmethod para criar operações que recebem a própria classe automaticamente.

A classe como primeiro argumento

O que muda com @classmethod

Coloque @classmethod imediatamente acima de um método para que Python entregue a classe no primeiro parâmetro. Por convenção, esse parâmetro se chama cls.

Diferentemente de self, cls não representa um objeto específico. Ele permite que o método consulte atributos definidos na própria classe, mesmo antes de existir uma instância.

Um método que consulta a classe

python
class ConfiguracaoCor:
    espaco = "RGB"

    @classmethod
    def descrever_espaco(cls, prefixo):
        return f"{prefixo}: {cls.espaco}"


print(ConfiguracaoCor.descrever_espaco("Modelo"))
# Modelo: RGB

Dica

Dois tipos de argumentos

Em descrever_espaco(cls, prefixo), cls é fornecido automaticamente por Python. Já prefixo é explícito: você o informa na chamada.

Como o acesso fornece cls

Classe, instância e o mesmo cls

Observe que as duas formas de acesso entregam a classe ConfiguracaoCor ao parâmetro cls.

Diagrama com chamadas pela classe e por uma instância convergindo para o parâmetro cls, que aponta para a classe ConfiguracaoCor; o argumento prefixo é mostrado como argumento explícito separado.

O acesso muda, mas cls continua sendo a classe — nunca a instância.

Chamando das duas formas

python
configuracao = ConfiguracaoCor()

print(ConfiguracaoCor.descrever_espaco("Modelo"))
print(configuracao.descrever_espaco("Espaço"))
# Modelo: RGB
# Espaço: RGB

A chamada pela instância é permitida, mas ela não é entregue em cls. O método continua ligado à classe e consulta ConfiguracaoCor.espaco por meio de cls.espaco.

Verifique a assinatura

Complete o método de classe

Complete os dois espaços para que o método receba a classe e retorne seu atributo nome:

class Paleta:
    nome = "vibrante"

    _____
    def mostrar_nome(____):
        return cls.nome

Regra essencial

Resumo

@classmethod em uma frase

  • Use @classmethod quando a operação precisa receber a classe, não um objeto específico.
  • cls é o primeiro parâmetro por convenção e é preenchido automaticamente.
  • Os demais parâmetros continuam sendo argumentos explícitos da chamada.
  • O método pode ser acessado pela classe ou por uma instância; nos dois casos, cls representa a classe.

Passo 2 de 6

Criar um construtor alternativo

Transforme uma representação textual de cor em um objeto CorRGB usando um método de classe.

Outra porta de entrada para a mesma classe

Do texto ao objeto

Um construtor alternativo aceita uma forma diferente de entrada e devolve uma nova instância. Em vez de exigir três números separados, CorRGB.de_texto("12, 180, 90") pode interpretar o texto e criar a cor correspondente.

A responsabilidade do método é dupla: interpretar a entrada e então chamar cls(...). Assim, a inicialização usual da classe continua sendo aplicada.

Fluxo do construtor alternativo

A conversão do texto acontece antes da criação da instância.

Diagrama mostrando a sequência: texto RGB separado por vírgulas, três componentes numéricos e uma instância de cor com amostras vermelha, verde e azul.

O método extrai componentes do texto e usa esses valores para inicializar um novo objeto.

Implementação com cls

Classe e construtor alternativo

O primeiro parâmetro continua sendo cls, recebido automaticamente pelo método de classe.

python
class CorRGB:
    def __init__(self, vermelho, verde, azul):
        for componente in (vermelho, verde, azul):
            if not 0 <= componente <= 255:
                raise ValueError("Cada componente deve estar entre 0 e 255")

        self.vermelho = vermelho
        self.verde = verde
        self.azul = azul

    @classmethod
    def de_texto(cls, texto):
        partes = texto.split(",")
        vermelho, verde, azul = (int(parte.strip()) for parte in partes)
        return cls(vermelho, verde, azul)

cor = CorRGB.de_texto("12, 180, 90")
print(cor.verde)  # 180

Exemplo

O que é devolvido?

CorRGB.de_texto("12, 180, 90") devolve uma instância de CorRGB, não a tupla (12, 180, 90).

Os valores extraídos são apenas uma etapa intermediária. O resultado público do construtor alternativo é o objeto criado por cls(vermelho, verde, azul).

Dica

Reaproveite as regras existentes

Ao chamar cls(...), você reutiliza o __init__. Por isso, uma entrada como "300, 0, 0" ainda resulta em ValueError, sem duplicar a validação no método de_texto.

Organize o fluxo

Da entrada ao objeto

Coloque as etapas de de_texto na ordem correta.

  1. Chamar `cls(vermelho, verde, azul)`.
  2. Retornar a instância criada.
  3. Separar o texto pelas vírgulas.
  4. Remover espaços e converter cada parte para `int`.

Complete o retorno correto

Construa a cor

Complete a última linha do método para devolver um objeto, e não uma tupla:

@classmethod
def de_texto(cls, texto):
    vermelho, verde, azul = (int(p.strip()) for p in texto.split(","))
    return ____

Passo 3 de 6

Preservar subclasses usando cls

Use cls em um construtor alternativo para que chamadas pela classe-base, por subclasses ou por instâncias preservem o tipo correto do objeto criado.

O tipo que chamou o método importa

Método herdado, classe preservada

Um construtor alternativo definido na classe-base também é herdado por suas subclasses. Em um @classmethod, cls é a classe pela qual o método foi acessado.

Assim, CorRGB.de_texto(...) recebe CorRGB em cls, enquanto CorDestaque.de_texto(...) recebe CorDestaque. Ao construir com cls(...), o mesmo código cria objetos do tipo apropriado.

Um método, dois tipos de resultado

Observe como a classe que acessa o método determina o valor de cls e, portanto, o tipo do objeto construído.

Diagrama mostrando uma classe-base de cor e uma subclasse de cor de destaque apontando para o mesmo construtor alternativo; a chamada da classe-base gera um objeto-base e a chamada da subclasse gera um objeto da subclasse.

Com cls(...), cada chamada produz uma instância da classe que acessou o método.

Use cls, não um nome fixo

Construtor alternativo herdável

A versão correta usa cls na última linha.

python
class CorRGB:
    def __init__(self, vermelho, verde, azul):
        self.vermelho = vermelho
        self.verde = verde
        self.azul = azul

    @classmethod
    def de_texto(cls, texto):
        vermelho, verde, azul = texto.split(",")
        return cls(int(vermelho), int(verde), int(azul))


class CorDestaque(CorRGB):
    pass


base = CorRGB.de_texto("10,20,30")
destaque = CorDestaque.de_texto("10,20,30")
pela_instancia = CorDestaque(1, 2, 3).de_texto("40,50,60")

assert type(base) is CorRGB
assert type(destaque) is CorDestaque
assert type(pela_instancia) is CorDestaque

Atenção

Não fixe CorRGB no retorno

Se o método terminasse com return CorRGB(...), toda chamada criaria uma CorRGB, até mesmo quando fosse acessado como CorDestaque.de_texto(...). Isso descarta a especialização da subclasse.

Dica

Compatibilidade do inicializador

Para cls(vermelho, verde, azul) funcionar em uma subclasse, o inicializador dela precisa aceitar esses três argumentos. Neste exemplo, CorDestaque herda o __init__ de CorRGB; se ela redefinir __init__, deve manter uma forma compatível ou adaptar o construtor alternativo.

Chamada pela instância também usa a classe

A instância não vira o primeiro argumento

Uma instância também pode acessar um método de classe. Mesmo em CorDestaque(1, 2, 3).de_texto("40,50,60"), o primeiro argumento automático continua sendo a classe CorDestaque, não aquela instância.

Por isso, a chamada cria uma nova CorDestaque; ela não altera nem reutiliza o objeto que foi usado para acessar o método.

Preveja o tipo

Considerando o código anterior, qual é o tipo exato retornado por CorDestaque.de_texto("7,8,9")?

Encontre a construção que quebra a especialização

Troque o nome fixo

Você encontrou este retorno em um construtor alternativo herdado:

return CorRGB(int(vermelho), int(verde), int(azul))

Explique qual substituição deve ser feita para que uma chamada por CorDestaque produza uma CorDestaque e justifique.

Escreva pelo menos 60 caracteres (0/60).

Passo 4 de 6

Definir uma operação com @staticmethod

Crie uma verificação de componentes RGB que recebe apenas os valores informados na chamada.

Sem self e sem cls

Uma operação sem receptor automático

Use @staticmethod quando uma operação associada à classe precisa somente dos argumentos que você informa na chamada. Diferentemente de um método de instância ou de classe, ela não recebe self nem cls automaticamente.

Por isso, a assinatura contém apenas os dados necessários para a operação.

Verificando componentes RGB

A verificação depende exclusivamente de r, g e b.

python
class CorRGB:
    @staticmethod
    def componentes_validos(r, g, b):
        return all(0 <= componente <= 255 for componente in (r, g, b))

print(CorRGB.componentes_validos(12, 200, 255))  # True
print(CorRGB.componentes_validos(12, 300, 255))  # False

Argumentos que chegam ao método

A imagem compara o argumento automático de um método de classe com os argumentos de uma operação estática.

Diagrama comparando classmethod, que recebe cls automaticamente além dos argumentos explícitos, com staticmethod, que recebe somente os argumentos explícitos r, g e b.

Em um staticmethod, somente os valores escritos entre parênteses chegam à função.

Acesso não muda os argumentos

Pela classe ou pela instância

Você pode acessar a operação estática pela classe ou por uma instância. Nas duas formas, Python não acrescenta nenhum argumento.

Assim, estes dois chamados fornecem exatamente 10, 20 e 30 para os parâmetros r, g e b.

Duas formas de chamar

python
cor = CorRGB()

print(CorRGB.componentes_validos(10, 20, 30))
print(cor.componentes_validos(10, 20, 30))
# Ambos exibem: True

Dica

Atenção ao vínculo

Um staticmethod não tem acesso automático à classe. Se a verificação precisasse consultar um limite que variasse conforme a classe, a escolha de vínculo deveria ser reconsiderada.

Complete a assinatura

Decorador correto

Complete o decorador para que o método receba apenas os três componentes explícitos:

class CorRGB:
_
def componentes_validos(r, g, b):
return all(0 <= c <= 255 for c in (r, g, b))

Verifique seu entendimento

Chamada por instância

Em cor.componentes_validos(10, 20, 30), o objeto cor é passado automaticamente como primeiro argumento.

Resumo

Essencial deste step

  • Use @staticmethod para uma operação ligada ao tipo que não precisa de self nem cls.
  • A assinatura de uma operação estática contém somente os parâmetros explicitamente necessários.
  • O acesso pela classe ou pela instância não altera os argumentos recebidos.
  • Sem cls automático, uma operação estática não consulta configurações variáveis da classe por conta própria.

Passo 5 de 6

Escolher onde a operação deve ficar

Escolha o local de uma operação com base no que ela precisa acessar e na clareza da interface.

Comece pela dependência

A pergunta que orienta a escolha

Antes de decidir pelo decorador, pergunte: de quais dados esta operação precisa?

  • Dados de um objeto específico → método de instância (self).
  • Identidade, configuração ou construção da classe chamada → método de classe (cls).
  • Nenhum vínculo automático, mas uma operação própria do domínio da classe → método estático.
  • Nenhum vínculo automático e nenhuma associação clara com a classe → função de módulo.

A ausência de self e cls não transforma, sozinha, uma função em método estático.

Mapa de decisão

O local da operação vem de sua dependência e de sua relação com o tipo.

Diagrama de decisão: dados de um objeto levam a método de instância; dados ou construção da classe levam a método de classe; operação específica do domínio sem vínculo automático leva a método estático; operação genérica sem relação clara leva a função de módulo.

Escolha primeiro o que a operação precisa acessar; depois avalie se colocá-la na classe torna a interface mais clara.

Quatro operações, quatro vínculos

Exemplo

Uma API de cores coerente

class CorRGB:
    limite = 255

    def como_hexadecimal(self):
        return f"#{self.vermelho:02X}{self.verde:02X}{self.azul:02X}"

    @classmethod
    def de_texto(cls, texto):
        vermelho, verde, azul = map(int, texto.split(","))
        return cls(vermelho, verde, azul)

    @staticmethod
    def componentes_validos(vermelho, verde, azul):
        return all(0 <= valor <= 255 for valor in (vermelho, verde, azul))


def normalizar_texto(texto):
    return " ".join(texto.strip().split()).casefold()
  • como_hexadecimal consulta componentes de uma cor: método de instância.
  • de_texto constrói pela classe chamada: método de classe.
  • componentes_validos verifica valores RGB recebidos e pertence naturalmente ao domínio de cores: método estático.
  • normalizar_texto serve a textos em geral, não apenas a cores: função de módulo.

Dica

Associação semântica importa

CorRGB.componentes_validos(10, 20, 30) informa bem o que está sendo validado. Já CorRGB.normalizar_texto(" Azul Claro ") sugere uma relação artificial entre normalização de texto e cores. Nesse caso, prefira normalizar_texto(...) no módulo.

Classifique pelas dependências

Onde cada operação deve ficar?

Relacione cada operação ao local mais adequado.

Toque em um item e depois no par correspondente.

Justifique uma escolha

Utilitário genérico ou método estático?

Uma equipe propõe colocar normalizar_texto(texto) dentro de CorRGB como @staticmethod. Justifique, em uma ou duas frases, por que você manteria essa operação como função de módulo.

Escreva pelo menos 80 caracteres (0/80).

Passo 6 de 6

Aplicar e revisar as escolhas

Refatore uma pequena API de cores e valide, em um script local, quando usar método de classe, método estático e função de módulo.

Planeje os vínculos da API

Três operações, três decisões

Você vai trabalhar com uma API formada por CorRGB e sua subclasse CorDestaque.

  • de_texto recebe uma representação alternativa e cria um objeto: é um método de classe.
  • componentes_validos só analisa os três números recebidos: é um método estático.
  • normalizar_texto serve para qualquer texto, não especificamente para cores: permanece uma função de módulo.

A decisão não é baseada apenas na ausência de self ou cls; ela depende de quais dados a operação precisa e de onde sua presença torna a interface mais clara.

Fluxo das responsabilidades

Observe quais dados entram em cada operação e o que ela produz.

Diagrama com uma entrada de texto seguindo para um construtor alternativo que cria CorRGB ou CorDestaque; três valores numéricos seguindo para uma validação estática; e uma entrada textual genérica seguindo para uma função independente fora das classes.

cls preserva o tipo construído; a validação estática recebe apenas valores explícitos; o utilitário genérico não precisa morar na classe.

Dica

Antes de executar

Crie um arquivo local chamado cores.py, copie o código da próxima tela e execute python cores.py no terminal, na pasta do arquivo. Não há bibliotecas externas nem arquivos adicionais.

Implemente e verifique

Versão refatorada

Nesta versão, de_texto interpreta a entrada e delega a criação para cls. Por isso, a mesma implementação herdada cria uma CorDestaque quando é acessada por essa subclasse.

Os asserts verificam o tipo exato, os componentes, a validação estática e o utilitário de módulo. Se tudo estiver correto, o script mostra quatro linhas e não gera erro.

cores.py

Copie, execute e observe as saídas.

python
def normalizar_texto(texto):
    return " ".join(texto.strip().lower().split())


class CorRGB:
    def __init__(self, vermelho, verde, azul):
        if not self.componentes_validos(vermelho, verde, azul):
            raise ValueError("Cada componente deve estar entre 0 e 255.")
        self.vermelho = vermelho
        self.verde = verde
        self.azul = azul

    @classmethod
    def de_texto(cls, texto):
        partes = texto.split(",")
        if len(partes) != 3:
            raise ValueError("Use três componentes separados por vírgulas.")

        vermelho, verde, azul = (int(parte.strip()) for parte in partes)
        return cls(vermelho, verde, azul)

    @staticmethod
    def componentes_validos(vermelho, verde, azul):
        return all(0 <= componente <= 255 for componente in (vermelho, verde, azul))


class CorDestaque(CorRGB):
    pass


cor_base = CorRGB.de_texto("12, 34, 56")
cor_destaque = CorDestaque.de_texto("200, 100, 50")

assert type(cor_base) is CorRGB
assert type(cor_destaque) is CorDestaque
assert (cor_base.vermelho, cor_base.verde, cor_base.azul) == (12, 34, 56)
assert CorRGB.componentes_validos(0, 128, 255) is True
assert CorRGB.componentes_validos(256, 128, 0) is False
assert normalizar_texto("  Azul   CLARO ") == "azul claro"

print(type(cor_destaque).__name__)
print((cor_base.vermelho, cor_base.verde, cor_base.azul))
print(CorRGB.componentes_validos(0, 128, 255))
print(normalizar_texto("  Azul   CLARO "))

Revise sua decisão

Relate a verificação

Após executar o código, registre: quais mudanças representam cada um dos três vínculos; qual foi o tipo exato de cor_destaque; quais verificações passaram; e por que normalizar_texto deve ficar fora de CorRGB.

Escreva pelo menos 100 caracteres (0/100).

Resumo

Critério final de escolha

  • Use método de instância quando a operação precisa dos dados de um objeto específico.
  • Use @classmethod quando a operação precisa da classe, especialmente para construir objetos com cls e respeitar subclasses.
  • Use @staticmethod para uma operação ligada semanticamente ao tipo, mas que recebe somente argumentos explícitos.
  • Mantenha uma função no módulo quando ela for genérica e colocá-la na classe não tornar a API mais clara.
  • assert permite verificar tipos exatos, valores construídos e resultados esperados durante uma refatoração local.

Tutorial concluído

Parabéns! Você concluiu: Definir métodos de classe e métodos estáticos

Muito bem! Agora você consegue criar construtores alternativos com classmethod, preservar subclasses com cls, definir operações estáticas e reconhecer quando um utilitário deve continuar como função de módulo.

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