get_type_hints no Python: leia anotações

Publicado em: 29/08/2026
Tempo de leitura: 6 minutos
Close-up image of a woman's hand holding a stack of spiral-bound notebooks and papers against a dark background.

typing.get_type_hints() recupera anotações de funções, métodos, classes e módulos em uma forma mais útil do que acessar diretamente __annotations__. A função pode resolver referências futuras, substituir aliases especiais, combinar anotações herdadas e, quando solicitado, preservar metadados de Annotated.

Esse poder exige cuidado: resolver anotações pode depender de namespaces, importar nomes e avaliar expressões. Neste guia, você aprenderá a usar get_type_hints em decorators, validadores, geradores de schema, injeção de dependências e documentação, além de tratar forward references, Annotated, classes genéricas, erros e segurança.

__annotations__ básico

def somar(a: int, b: int) -> int:
    return a + b

print(somar.__annotations__)

O dicionário costuma conter as anotações declaradas. Porém, dependendo da versão e das opções do módulo, valores podem estar armazenados como strings ou objetos ainda não resolvidos.

Usando get_type_hints

from typing import get_type_hints

hints = get_type_hints(somar)
print(hints)

A função retorna um mapping com parâmetros e a chave especial return. Tipos são resolvidos no contexto apropriado sempre que possível.

Referências futuras

class Usuario:
    gerente: "Usuario | None"

print(Usuario.__annotations__)
print(get_type_hints(Usuario))

O acesso direto pode mostrar uma string. get_type_hints tenta resolver o nome Usuario e construir a união real.

from __future__ import annotations

Quando o módulo usa anotações adiadas, muitas expressões ficam armazenadas de forma não avaliada. get_type_hints é uma forma centralizada de obter objetos de tipo resolvidos, mas precisa que os nomes referenciados estejam disponíveis.

Namespaces globais e locais

get_type_hints(objeto, globalns=globais, localns=locais)

globalns e localns permitem controlar a resolução. Isso é útil para classes criadas dinamicamente, funções aninhadas e ferramentas que inspecionam código fora do módulo original. Forneça mappings corretos e mínimos.

Falhas de resolução

class Pedido:
    cliente: "Cliente"

Se Cliente não existe no namespace, get_type_hints pode lançar NameError. Ferramentas devem capturar erros, indicar qual anotação falhou e decidir se continuam com valores não resolvidos.

Annotated é removido por padrão

from typing import Annotated

def idade(valor: Annotated[int, "0 a 130"]) -> None:
    ...

Por padrão, get_type_hints pode retornar apenas int, removendo metadados extras.

Preservando extras

hints = get_type_hints(idade, include_extras=True)

Com include_extras=True, Annotated, Required, NotRequired e outros qualificadores relevantes podem ser preservados para ferramentas de schema e validação. Consulte Annotated no Python.

Inspecionando Annotated

from typing import get_args, get_origin

anotacao = hints["valor"]
print(get_origin(anotacao))
print(get_args(anotacao))

get_origin() identifica o contêiner de typing e get_args() retorna tipo base e metadados. Não dependa de representações de string.

Funções decoradas

Decorators devem usar functools.wraps para preservar metadados e __wrapped__. get_type_hints pode seguir a função apropriada, mas wrappers mal construídos podem esconder a assinatura.

from functools import wraps

def log(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs)
    return wrapper

Métodos e classes

class Configuracao:
    host: str
    porta: int

print(get_type_hints(Configuracao))

Para classes, a função considera anotações ao longo da MRO e combina bases, com membros da classe derivada tendo prioridade. Isso ajuda frameworks de modelos.

Herança

class Base:
    id: int

class Derivada(Base):
    nome: str

get_type_hints(Derivada)

O resultado pode incluir id e nome. Se a subclasse redefine um campo, sua anotação substitui a base.

ClassVar e Final

Com include_extras=True, qualificadores podem permanecer disponíveis. Um framework deve decidir se trata ClassVar como campo de instância, configuração da classe ou item ignorado.

TypedDict

get_type_hints recupera tipos de valores, mas presença obrigatória e opcional também depende de __required_keys__ e __optional_keys__. Para schemas completos, combine as fontes.

Dataclasses

Em dataclasses, get_type_hints resolve tipos, enquanto dataclasses.fields() fornece defaults, factories, flags e metadados de campo. Um serializador normalmente precisa das duas APIs.

Aliases

Aliases modernos podem permanecer como entidades próprias ou ser avaliados conforme a API usada. Ferramentas devem decidir quando expandir TypeAliasType e quando preservar seu nome. Consulte TypeAliasType no Python.

Genéricos

from typing import Generic, TypeVar

T = TypeVar("T")

class Caixa(Generic[T]):
    valor: T

get_type_hints na classe recupera T, mas não especializa automaticamente um objeto Caixa[int] em todos os contextos. Resolver parâmetros concretos exige acompanhar __orig_bases__, get_origin() e get_args(), com cuidado.

Objetos não suportados

Nem todo objeto possui anotações significativas. Bibliotecas devem verificar o tipo de entrada e produzir erros claros. Funções built-in e extensões C podem não expor metadados completos.

Avaliação e segurança

Anotações podem conter expressões. Avaliá-las pode executar código arbitrário em alguns cenários. Não processe anotações de fontes não confiáveis como se fossem dados inertes. Inspecione código confiável, limite namespaces e evite carregar módulos desconhecidos apenas para resolver tipos.

Não use como validador direto

get_type_hints informa o contrato declarado, mas não testa valores. Para validar uma lista, união, TypedDict ou Annotated, uma biblioteca precisa interpretar cada construção e produzir regras de runtime.

Cache

Resolver anotações repetidamente pode custar tempo. Frameworks podem armazenar resultados por função ou classe. Considere invalidação se o projeto modifica anotações dinamicamente, embora esse padrão seja melhor evitado.

Importações circulares

Forward references ajudam a escrever tipos sem importar tudo no topo, mas get_type_hints ainda precisa resolver os nomes quando executado. Use TYPE_CHECKING, módulos de modelos bem organizados e namespaces explícitos. Ferramentas podem adiar a resolução até que a aplicação esteja inicializada.

TYPE_CHECKING

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from pacote import Cliente

A importação existe apenas para o analisador. Em runtime, get_type_hints pode não encontrar Cliente. Se uma ferramenta precisa resolver a referência, disponibilize o nome de outra forma ou forneça globalns.

Exemplo de validador simples

from inspect import signature
from typing import get_type_hints


def validar_chamada(func, *args, **kwargs):
    sig = signature(func)
    ligados = sig.bind(*args, **kwargs)
    hints = get_type_hints(func)
    for nome, valor in ligados.arguments.items():
        esperado = hints.get(nome)
        if isinstance(esperado, type) and not isinstance(valor, esperado):
            raise TypeError(f"{nome} deve ser {esperado.__name__}")

Esse exemplo suporta apenas classes simples. Uniões, genéricos e Protocol exigem interpretação mais sofisticada. Não transforme uma demonstração em sistema de validação completo.

Gerador de documentação

Uma ferramenta pode combinar inspect.signature(), docstrings e get_type_hints para listar parâmetros, defaults, retornos e metadados. Preserve aliases públicos e Annotated quando eles melhorarem a documentação.

Erros comuns

  • Usar apenas __annotations__: referências podem permanecer strings.
  • Esquecer include_extras: metadados e qualificadores podem desaparecer.
  • Ignorar NameError: referências futuras podem não ser resolvidas.
  • Avaliar código não confiável: anotações não são necessariamente dados seguros.
  • Tratar hints como validação: ainda é preciso verificar valores.
  • Resolver em cada chamada: cache pode ser necessário.

Exemplo completo: registro de handlers

from typing import Annotated, get_type_hints

class Evento: ...
class Contexto: ...

handlers: dict[type[Evento], object] = {}

def handler(func):
    hints = get_type_hints(func, include_extras=True)
    evento = hints.get("evento")
    retorno = hints.get("return")
    if not isinstance(evento, type) or not issubclass(evento, Evento):
        raise TypeError("parâmetro evento inválido")
    if retorno is not None and retorno is not type(None):
        raise TypeError("handler deve retornar None")
    handlers[evento] = func
    return func

@handler
def processar(evento: Evento, contexto: Contexto) -> None:
    ...

O decorator usa as anotações para registrar funções. Uma implementação real também verificaria nomes, quantidade de parâmetros, subclasses específicas e mensagens de erro.

Quando evitar introspecção

Se a interface pode ser declarada explicitamente, um registro com argumentos costuma ser mais simples e previsível. Use get_type_hints quando as próprias anotações são parte intencional da API, como em frameworks, serializadores, documentação e injeção de dependências.

Conclusão

get_type_hints() é a principal ferramenta para obter anotações resolvidas em runtime. Ele trata referências futuras, herança e extras de typing melhor que o acesso direto a __annotations__.

A documentação oficial de get_type_hints no módulo typing explica os parâmetros. Use namespaces controlados, preserve extras quando necessário, trate falhas de resolução e nunca avalie anotações não confiáveis sem considerar o risco de execução de código.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    Estrutura de código e XML para canonicalização com Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    ElementTree canonicalize: normalize XML no Python

    Aprenda ElementTree canonicalize no Python para comparar XML, gerar hashes estáveis e controlar namespaces, espaços e comentários.

    Ler mais

    Tempo de leitura: 5 minutos
    22/10/2026
    Código de programação Python em uma tela
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    T-strings e templatelib: interpolação estruturada

    Aprenda t-strings e string.templatelib no Python para processar interpolações, criar renderizadores seguros e preservar dados estruturados.

    Ler mais

    Tempo de leitura: 6 minutos
    22/10/2026
    Banco SQLite e código Python para exportação seletiva com iterdump
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    SQLite iterdump: crie dumps seletivos no Python

    Aprenda sqlite3.Connection.iterdump com filtro para gerar dumps seletivos, validar dependências e restaurar bancos com segurança.

    Ler mais

    Tempo de leitura: 5 minutos
    21/10/2026
    Código e arquivos representando compressão de dados no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    compression.zstd: Zstandard rápido no Python

    Aprenda a usar compression.zstd no Python para comprimir e descomprimir dados com desempenho, streaming e segurança.

    Ler mais

    Tempo de leitura: 7 minutos
    21/10/2026
    Arquivo de configuração e estrutura de código para ConfigParser no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    ConfigParser: leia INI sem seção no Python

    Aprenda a ler arquivos INI sem cabeçalho usando ConfigParser, com validação, tipos, compatibilidade e escrita segura.

    Ler mais

    Tempo de leitura: 5 minutos
    20/10/2026
    Dados binários e memória de computador representando memoryview no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    memoryview count e index: busque sem copiar

    Aprenda memoryview count e index no Python para buscar valores em buffers sem cópias e validar dados binários com eficiência.

    Ler mais

    Tempo de leitura: 5 minutos
    20/10/2026