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

    A laptop screen showing a code editor with visible programming code in a dimly lit environment.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    runtime_checkable no Python: Protocol em runtime

    Aprenda runtime_checkable no Python para testar Protocol com isinstance, entender limites e criar contratos estruturais seguros.

    Ler mais

    Tempo de leitura: 6 minutos
    29/08/2026
    Close-up of a laptop screen with code and a coffee mug, perfect for tech abstract themes.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    Unpack no Python: kwargs e tipos variádicos

    Aprenda typing.Unpack no Python para tipar **kwargs com TypedDict, expandir tuplas variádicas e preservar assinaturas precisas.

    Ler mais

    Tempo de leitura: 6 minutos
    29/08/2026
    High-angle view of woman coding on a laptop, with a Python book nearby. Ideal for programming and tech content.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    Required e NotRequired: campos opcionais no TypedDict

    Aprenda Required e NotRequired no Python para controlar chaves obrigatórias e opcionais em TypedDict com contratos claros.

    Ler mais

    Tempo de leitura: 6 minutos
    29/08/2026
    Detailed view of programming code in a dark theme on a computer screen.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    ReadOnly no Python: proteja campos TypedDict

    Aprenda ReadOnly no Python para marcar campos TypedDict como somente leitura, modelar contratos imutáveis e evitar alterações acidentais.

    Ler mais

    Tempo de leitura: 6 minutos
    29/08/2026
    A detailed image of a reticulated python showcasing its patterned scales and intricate skin texture.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    TypeAliasType no Python: aliases em runtime

    Aprenda TypeAliasType no Python para criar aliases explícitos, inspecionar tipos em runtime e modelar APIs genéricas com segurança.

    Ler mais

    Tempo de leitura: 7 minutos
    29/08/2026
    High-angle view of woman coding on a laptop, with a Python book nearby. Ideal for programming and tech content.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    overload no Python: assinaturas precisas

    Aprenda typing.overload no Python para criar assinaturas precisas com Literal, None, genéricos, métodos e retornos dependentes dos argumentos.

    Ler mais

    Tempo de leitura: 8 minutos
    29/08/2026