TypeVarTuple no Python: genéricos variádicos

Publicado em: 29/08/2026
Tempo de leitura: 6 minutos
High-angle view of woman coding on a laptop, with a Python book nearby. Ideal for programming and tech content.

typing.TypeVarTuple representa uma quantidade variável de parâmetros de tipo. Enquanto um TypeVar corresponde a um único tipo, TypeVarTuple pode capturar uma sequência heterogênea como (int, str, bytes) e reutilizá-la em outra posição. O recurso permite criar genéricos variádicos, preservar tipos posicionais de tuplas e modelar formas de arrays e tensores.

Neste guia, você aprenderá a declarar TypeVarTuple, expandi-lo com Unpack ou estrela, distinguir tuplas homogêneas de heterogêneas, adicionar prefixos e sufixos, criar classes com número variável de parâmetros, modelar dimensões e entender limites de inferência e runtime.

Limite do TypeVar comum

from typing import TypeVar

T = TypeVar("T")

def repetir(valor: T) -> tuple[T, T]:
    return (valor, valor)

TypeVar preserva um tipo. Ele não consegue capturar uma tupla com quantidade desconhecida de posições diferentes.

Tupla homogênea

def contar(valores: tuple[int, ...]) -> int:
    return len(valores)

tuple[int, ...] aceita qualquer quantidade de inteiros. Todas as posições compartilham o mesmo tipo. Isso é diferente de preservar tuple[int, str, bool] como três tipos distintos.

Declarando TypeVarTuple

from typing import TypeVarTuple

Ts = TypeVarTuple("Ts")

Ts representa zero ou mais tipos posicionais. Para usá-lo em uma anotação, é necessário expandi-lo.

Expandindo com Unpack

from typing import Unpack

def identidade_tupla(
    valores: tuple[Unpack[Ts]],
) -> tuple[Unpack[Ts]]:
    return valores

Se a entrada é tuple[int, str], o retorno também é tuple[int, str]. Cada posição é preservada.

Sintaxe estrelada

def identidade_tupla(
    valores: tuple[*Ts],
) -> tuple[*Ts]:
    return valores

Em contextos modernos, *Ts é equivalente a Unpack[Ts]. A forma explícita continua útil para compatibilidade e leitura em versões anteriores.

Adicionar um prefixo

def com_nome(
    valores: tuple[*Ts],
) -> tuple[str, *Ts]:
    return ("registro", *valores)

Uma entrada tuple[int, bool] produz tuple[str, int, bool]. O grupo variádico permanece intacto.

Adicionar um sufixo

def com_status(
    valores: tuple[*Ts],
) -> tuple[*Ts, bool]:
    return (*valores, True)

Prefixos e sufixos fixos ajudam a modelar transformações de registros posicionais.

Remover a primeira posição

def cauda(
    valores: tuple[object, *Ts],
) -> tuple[*Ts]:
    primeiro, *resto = valores
    return tuple(resto)

A anotação descreve uma tupla com pelo menos um elemento. A implementação pode exigir cast dependendo da capacidade do analisador de relacionar a lista intermediária com a tupla variádica.

Classes genéricas variádicas

from typing import Generic

class Registro(Generic[*Ts]):
    def __init__(self, valores: tuple[*Ts]) -> None:
        self.valores = valores

Especializações podem ter números diferentes de parâmetros:

linha: Registro[int, str]
pixel: Registro[int, int, int, float]

A classe preserva a estrutura de cada instância no sistema de tipos.

API de zip tipada

Uma função zip genérica completa é difícil porque relaciona vários iteráveis e uma tupla de saída. TypeVarTuple permite expressar partes dessa relação, mas a inferência de iteráveis individuais pode exigir overloads ou recursos adicionais.

Modelando formas

Shape = TypeVarTuple("Shape")

class Array(Generic[*Shape]):
    ...

Uma matriz pode ser Array[Altura, Largura] e uma imagem Array[Altura, Largura, Canais]. Os tipos podem ser marcadores de dimensão, não valores numéricos reais.

Adicionar dimensão de batch

class Batch: ...

def adicionar_batch(x: Array[*Shape]) -> Array[Batch, *Shape]:
    ...

A operação preserva todas as dimensões existentes e adiciona uma no início. Essa relação é valiosa em bibliotecas numéricas e de machine learning.

Transposição

Reordenar um grupo variádico arbitrário é difícil. TypeVarTuple preserva uma sequência, mas não oferece operações gerais de reversão ou permutação no sistema de tipos. Para matrizes de duas dimensões, overloads ou parâmetros explícitos podem ser mais claros.

Um TypeVarTuple por lista

Uma lista de parâmetros não pode conter dois grupos variádicos sem uma forma não ambígua de separá-los:

# Ambíguo: tuple[*As, *Bs]

O analisador não saberia onde termina o primeiro grupo. Use um único grupo com elementos fixos ao redor.

TypeVarTuple pode ser vazio

vazio: Registro[()]
# A sintaxe concreta varia; o conceito é uma sequência sem tipos.

Funções variádicas precisam considerar o caso zero quando não exigem prefixo ou sufixo fixo. Se pelo menos uma posição é necessária, declare um elemento fixo.

Restrições e bounds

Diferentemente de TypeVar, TypeVarTuple não oferece exatamente os mesmos mecanismos de bound e constraints para cada elemento. Se todos os elementos precisam seguir uma interface, talvez uma tupla homogênea ou outra abstração seja melhor.

TypeVarTuple e Unpack

TypeVarTuple define o grupo. Unpack expande o grupo em uma lista de parâmetros ou posições. O artigo sobre Unpack no Python mostra também o uso em **kwargs.

Inferência em literais de tupla

resultado = identidade_tupla((1, "a", True))

O analisador pode inferir tuple[int, str, bool]. Use assert_type() para registrar a expectativa em testes estáticos.

Listas não preservam posições

Uma lista normalmente possui um tipo de elemento comum, como list[int | str]. Ela não preserva tipos por índice. TypeVarTuple é naturalmente adequado a tuplas e listas de parâmetros genéricos, não a listas mutáveis heterogêneas.

Callable e parâmetros

TypeVarTuple não substitui ParamSpec para assinaturas de funções. ParamSpec preserva tipos de parâmetros, incluindo nomes, categorias e kwargs. TypeVarTuple preserva uma sequência posicional de tipos. Escolha conforme a relação.

Comparação com overload

Sem TypeVarTuple, uma biblioteca poderia escrever overloads para tuplas de uma, duas, três e quatro posições. O grupo variádico elimina repetição quando a transformação é uniforme para qualquer tamanho.

Runtime

TypeVarTuple não valida comprimento nem valores durante execução. Uma classe ainda precisa armazenar e verificar dados normalmente. Os parâmetros genéricos podem ser apagados ou acessíveis apenas parcialmente por introspecção.

Introspecção

get_origin() e get_args() ajudam a examinar especializações, mas objetos e classes genéricas nem sempre preservam todas as informações após construção. Não baseie invariantes de segurança apenas em argumentos de typing.

Compatibilidade

Use typing_extensions.TypeVarTuple e Unpack para versões anteriores. O suporte depende também do analisador. Atualize mypy ou pyright e teste a sintaxe escolhida.

Erros comuns

  • Usar TypeVarTuple sem expansão: ele precisa aparecer como *Ts ou Unpack[Ts].
  • Confundir com tuple[T, …]: TypeVarTuple preserva tipos diferentes por posição.
  • Criar dois grupos variádicos: a divisão fica ambígua.
  • Esperar validação de forma em runtime: é uma relação estática.
  • Usar no lugar de ParamSpec: assinaturas de callables precisam de nomes e categorias.
  • Modelar detalhes que o analisador não suporta: simplifique a API quando necessário.

Exemplo completo: pipeline de registros

from typing import Generic, TypeVarTuple

Campos = TypeVarTuple("Campos")

class Linha(Generic[*Campos]):
    def __init__(self, dados: tuple[*Campos]) -> None:
        self.dados = dados


def numerar(linha: Linha[*Campos]) -> Linha[int, *Campos]:
    return Linha((1, *linha.dados))


def marcar(linha: Linha[*Campos]) -> Linha[*Campos, bool]:
    return Linha((*linha.dados, True))

entrada = Linha(("Ana", 42.0))
numerada = numerar(entrada)
marcada = marcar(numerada)

O tipo evolui de Linha[str, float] para Linha[int, str, float] e depois Linha[int, str, float, bool]. Cada transformação conserva as posições anteriores.

Testes estáticos

from typing import assert_type

assert_type(numerada.dados, tuple[int, str, float])
assert_type(marcada.dados, tuple[int, str, float, bool])

Esses testes protegem a inferência durante mudanças na implementação ou nas anotações.

Quando evitar TypeVarTuple

Use uma dataclass ou NamedTuple quando os campos possuem nomes e significado estável. Use tuple homogênea quando todos os elementos compartilham tipo. Use ParamSpec para wrappers de função. Use TypeVarTuple quando a quantidade de posições varia e a relação precisa preservar cada tipo.

Conclusão

TypeVarTuple estende genéricos Python para sequências variáveis de tipos. Ele preserva tuplas heterogêneas, cria classes com vários parâmetros e modela transformações de forma sem escrever dezenas de overloads.

A documentação oficial de TypeVarTuple no módulo typing define as regras. Use-o com Unpack ou estrela, mantenha um único grupo variádico por lista e confirme o comportamento com testes estáticos nos analisadores suportados.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    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

    assert_type e reveal_type: teste inferência de tipos

    Aprenda assert_type e reveal_type no Python para inspecionar inferência, testar APIs tipadas e evitar regressões no analisador.

    Ler mais

    Tempo de leitura: 6 minutos
    29/08/2026
    Close-up image of a woman's hand holding a stack of spiral-bound notebooks and papers against a dark background.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    get_type_hints no Python: leia anotações

    Aprenda get_type_hints no Python para resolver referências futuras, ler Annotated e inspecionar funções e classes com segurança.

    Ler mais

    Tempo de leitura: 6 minutos
    29/08/2026
    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