A função type() em Python é uma função básica para a ma­ni­pu­la­ção de tipos. Como parte da im­ple­men­ta­ção de Python, ela pertence ao núcleo dessa linguagem.

Para que serve a função type() em Python?

A função type() em Python é usada em dois cenários di­fe­ren­tes:

  1. Para obter o tipo de um objeto Python.
  2. Para criar di­na­mi­ca­mente uma nova classe.

Vamos con­si­de­rar o primeiro caso, que ocorre com muito mais frequên­cia no uso diário.

Obter tipo de objeto com type()

Python é uma linguagem dinâmica. Isso significa que seus tipos são de­ter­mi­na­dos somente durante o tempo de execução, sendo vin­cu­la­dos a valores em vez de a variáveis. Dessa cir­cuns­tân­cia surge a ne­ces­si­dade de de­ter­mi­nar o tipo de um objeto no tempo de execução.

Vamos chamar a função Python type() e passar um objeto como o único parâmetro. Em troca, obtemos o tipo do objeto, como int ou str:

# O tipo de `42` é `int`
assert type(42) == int
# O tipo de `str(42)` é `str`
assert type(str(42)) == str
Python

Se chamarmos a função type() no REPL de Python, a re­pre­sen­ta­ção textual do objeto retornado men­ci­o­nará “class” em vez de “type”:

# Retorna "<class 'int'>" no REPL
type(42)
Python

O que parece confuso a princípio faz todo o sentido, porque, em Python, “tudo é um objeto”. Em Python, o tipo de um objeto cor­res­ponde à classe dele. Assim, chamar a função type() é ge­ral­mente equi­va­lente a ler o atributo __class__:

# Deve valer na maioria dos casos
assert type(obj) é obj.__class__
Python

Criar novo tipo com type()

Agora, vamos explorar o segundo uso possível da função type(). Quando chamada com três ar­gu­men­tos, ela nos permite a criação dinâmica de um novo tipo:

type(name, bases, dict, **kwds)
Python

Nessa forma, a função type() em Python se comporta de maneira se­me­lhante à palavra-chave class. O código type = type("Type", bases, dict) pode ser pensado como uma definição de classe equi­va­lente:

class <Type>(<bases>):
    <dict>
Python

Abaixo está um exemplo de uso do type() em Python para criar novos tipos. Aqui está uma visão geral dos ar­gu­men­tos:

name bases dict **kwds
Nome do novo tipo como string Tupla com classes base Di­ci­o­ná­rio com atributos da nova classe Ar­gu­men­tos adi­ci­o­nais para ins­tan­ci­a­Ã§Ã£o da me­ta­classe
Dica

Com o Deploy Now da IONOS, você pode implantar sites e apli­ca­ti­vos pelo GitHub.

Como a função type() em Python funciona?

Se você usar a função type() para de­ter­mi­nar o tipo de um objeto, o valor retornado não será uma string, mas um objeto in­de­pen­dente:

# O valor retornado por `type(42)` não é uma string
assert type(42) != 'int'
# Obtemos um objeto chamado `int`
assert type(42) == int
Python

Vamos observar alguns exemplos de valores re­tor­na­dos pela função type() para objetos de di­fe­ren­tes tipos:

# Objetos Python de diferentes tipos
diferentes_objs = None, True, 42, 'John', ('Walter', 'White'), ...
# Imprima o tipo de cada objeto
for obj in diferentes_objs:
    print(f"{obj}: {type(obj)}")
Python
Chamada de type() Re­pre­sen­ta­Ã§Ã£o textual
type(None) <class 'NoneType'>
type(True) <class 'bool'>
type(42) <class 'int'>
type('John') <class 'str'>
type(('Walter', 'White')) <class 'tuple'>
type(...) <class 'ellipsis'>

Surge então a pergunta: qual é o tipo do objeto retornado por type()? Vamos tentar descobrir. Chamamos a função Python type() e passamos o valor retornado de outra chamada de type():

# Retorna: "<class 'type'>"
type(type(42))
Python

Isso mostra que, além da função type() embutida em Python, existe o tipo type, que possui o mesmo nome. Esse tipo re­pre­senta todos os outros tipos em Python, conforme ilustrado no exemplo:

# Objetos Python diferentes
diferentes_objs = None, True, 42, 'John', ('Walter', 'White'), ...
# Verifique o tipo do tipo de cada objeto
for obj in diferentes_objs:
    # Mostre que o tipo do tipo é sempre `type`
    assert type(type(obj)) é type
Python

Assim, o tipo de qualquer tipo em Python é type. Se isso parece confuso, espere até descobrir que o tipo do objeto type é outro type. Isso pode ser con­ti­nu­ado in­de­fi­ni­da­mente, como uma cobra mordendo o próprio rabo:

# É `type` o tempo todo
assert type(type(type(type))) é type
Python

Para es­cla­re­cer qualquer confusão, é essencial que você se aprofunde no sistema de pro­gra­ma­ção orientada a objetos (OOP) de Python. O objeto embutido type em Python re­pre­senta uma me­ta­classe. Uma me­ta­classe se comporta, em relação a uma classe, como uma classe se comporta em relação a um objeto. Em outras palavras, uma me­ta­classe funciona como um modelo para uma classe, enquanto uma classe funciona como um modelo para um objeto:

Modelo Instância
Classe Objeto
Me­ta­classe Classe
exemplo: type int, str, etc.
exemplo: int 42
exemplo: str “Walter White”

Como usar a função type() em Python?

A função type() em Python é comumente usada para recuperar o tipo de um objeto no tempo de execução. Essa fun­ci­o­na­li­dade é valiosa, porque o Python é uma linguagem di­na­mi­ca­mente tipada. Em contraste, lin­gua­gens es­ta­ti­ca­mente tipadas, como Java, exigem que os tipos das variáveis sejam de­cla­ra­dos, não podendo ser alterados no tempo de execução.

// Declarar variável como `boolean`
boolean resposta;
// Tentar atribuir valor `int`
// Gera erro de tipo
resposta = 42;
Java

Por outro lado, variáveis em Python são sim­ples­mente nomes que se referem a valores tipados. A qualquer momento durante a execução do código, um nome pode ser re­fe­ren­ci­ado a um valor de tipo diferente. Portanto, para de­ter­mi­nar o tipo de uma variável Python no tempo de execução, você precisa da função type():

# Atribuir valor booleano
resposta = True
# Mostrar que o tipo é `bool`
assert type(resposta) é bool
# Reatribuir valor inteiro
resposta = 42
# Mostrar que o tipo agora é `int`
assert type(resposta) é int
Python

Verificar tipo de argumento de função com type()

Ao definir uma função, muitas vezes é ne­ces­sá­rio verificar se os ar­gu­men­tos cumprem certos critérios. Isso inclui checar se os ar­gu­men­tos estão dentro de certos limites ou confirmar que são de tipos adequados. Ao realizar essas ve­ri­fi­ca­ções, você pode evitar po­ten­ci­ais erros de tempo de execução.

Vamos ilustrar o uso da função type() com um exemplo. De­fi­ni­re­mos uma função que soma uma lista de números. Para que ela funcione, pre­ci­sa­mos garantir que cada argumento seja um número. Para isso, usamos type() dentro de uma instrução assert:

# Função para somar argumentos numéricos
def soma_numeros(*args):
  resultado = 0
  # Verificar cada argumento
  for arg in args:
    # Abort com mensagem de erro se o argumento não for `int` ou `float`
    assert type(arg) in (int, float), f"Argumento `{arg}` não é um número"
    # Adicionar o valor do argumento ao total
    resultado += arg
  return resultado
 
# Mostrar que funciona para números
assert soma_numeros(35, 7) == 42
# O seguinte falhará
soma_numeros(29, 'treze')
Python

Depurar com a função type() no REPL

Uma das vantagens de lin­gua­gens in­ter­pre­ta­das, como Python, é a execução in­te­ra­tiva de códigos no REPL (Read-Eval-Print-Loop), que pos­si­bi­lita pro­to­ti­pa­gem rápida e depuração por meio da inspeção de objetos na memória.

Vamos imaginar o seguinte cenário. Nosso código contém uma variável resposta, que deveria conter um valor booleano. Des­co­bri­mos que o tipo não cor­res­ponde às nossas ex­pec­ta­ti­vas e usamos a função type() em Python para exibir o tipo. Como se constata, es­cre­ve­mos aci­den­tal­mente o valor booleano entre aspas – um erro comum, es­pe­ci­al­mente entre os ini­ci­an­tes:

# Atribuído acidentalmente como string
resposta = 'False'
# A asserção falhará
assert type(resposta) é bool
# Corrigir para valor booleano
resposta = False
# Agora a asserção é válida
assert type(resposta) é bool
Python

Criar classes di­na­mi­ca­mente com a função type()

Como já de­mons­trado, classes em Python podem ser criadas di­na­mi­ca­mente, ou seja, no tempo de execução, pela função type(). Isso é útil, entre outras coisas, em famílias de classes. Vamos de­mons­trar o conceito de famílias de classes com um exemplo que usa tags HTML. Pri­mei­ra­mente, criamos uma classe base Tag, para que objetos dessa classe possam se re­pre­sen­tar como código HTML.

# Classe representando uma tag HTML
class Tag:
    # Inicializar tag HTML com conteúdo
    def __init__(self, *args):
        # Juntar conteúdo da tag
        self.content = "".join([arg.__str__() for arg in args])
    # Representação como string retorna HTML
    def __str__(self):
        return f"<{self.name}>{self.content}</{self.name}>"
Python

Para es­pe­ci­a­li­zar a classe base Tag, por herança, para tags HTML es­pe­cí­fi­cas, como <p> e <h1>, podemos utilizar novamente a função type(). Vamos ilustrar a situação com um exemplo:

# Criar classe `P`
P = type('P', (Tag,), {"name": 'p'})
Python
  1. Nome da nova classe como string.

  2. Tupla com classes base.Python permite heranças múltiplas; para derivação de apenas uma classe, usamos a notação (NomeClasse,).

  3. Di­ci­o­ná­rio com o nome da classe e as entradas adi­ci­o­nais, se ne­ces­sá­rio. Essas entradas também podem ser funções. Pos­te­ri­or­mente, ins­tan­ci­a­mos uma tag p e ve­ri­fi­ca­mos se a re­pre­sen­ta­ção funciona cor­re­ta­mente:

# Instanciar tag `p`
cumprimento = P("Olá, mundo")
assert str(cumprimento) == '&lt;p&gt;Olá, mundo&lt;/p&gt;'
Python

O mesmo efeito pode ser alcançado por definição de classe análoga:

# Criar classe `P`
class P(Tag):
    name = 'p'
Python

Como no outro exemplo, criamos classes para títulos usando type(). Fazendo uso da ca­pa­ci­dade de criação dinâmica de classes com type(), podemos criar classes para todos os seis níveis de títulos, de uma só vez, usando a com­pre­en­são de listas:

h_1_a_6 = (f"h{n}" for n in range(1, 7))
titulos = [type(titulo, (Tag,), {"name": titulo}) for titulo in h_1_a_6]
Python

Como você pode ver, vale a pena usar a função type() para criar várias sub­clas­ses re­la­ci­o­na­das. De­mons­tra­mos essa abordagem usando o exemplo mais complexo de definição de classes para modelar cartas de baralho. Pri­mei­ra­mente, definimos uma su­per­classe, Carta, usando a palavra-chave class:

# Classe representando carta de baralho abstrata
class Carta:
    def __init__(self, numero):
        self.numero = numero
    # Representação como string
    def __str__(self):
        return f"{self.numero} de {self.naipes}"
Python

Em seguida, criamos sub­clas­ses para os quatro naipes usando type():

# Criar tipos concretos para cada naipe
Paus = type('Paus', (Carta,), {'naipe': 'Paus'})
Ouros = type('Ouros', (Carta,), {'naipe': 'Ouros'})
Copas = type('Copas', (Carta,), {'naipe': 'Copas'})
Espadas = type('Espadas', (Carta,), {'naipe': 'Espadas'})
Python

Agora, as cartas in­di­vi­du­ais podem ser ins­tan­ci­a­das:

# Instanciar um 7 de Espadas
carta = Espadas(7)
# Mostrar que funcionou
assert str(carta) == '7 de Espadas'
Python

Quais são os limites da função type()?

A função type() em Python é útil, mas em alguns casos ela pode atingir seu limite. Fe­liz­mente, para essas situações, a linguagem oferece algumas soluções al­ter­na­ti­vas. Vamos analisá-las.

Quebrar hi­e­rar­quias de herança com isinstance()

type() somente determina o tipo real de um objeto em Python, ignorando a hi­e­rar­quia de herança. Vamos ilustrar esse dilema reu­ti­li­zando o nosso exemplo de cartas de baralho. O tipo da carta 7 de espadas deveria ser tanto “carta de baralho” quanto “espadas”. No entanto, com type(), isso não ocorre:

# Criar Sete de Espadas
carta = Espadas(7)
# Nossa carta é uma Espada, certo
assert type(carta) é Espadas
# Mas não é uma carta??
assert type(carta) não é Carta
Python

Para quebrar cor­re­ta­mente o po­li­mor­fismo sub­ja­cente, temos de usar a função isinstance().

# Sete de Espadas é `Espadas`
assert isinstance(carta, Espadas)
# E também é uma `Carta`
assert isinstance(carta, Carta)
Python

Sim­pli­fi­car detecção de tipo de objetos com match-case

Como já de­mons­trado, a função type() é fre­quen­te­mente usada para de­ter­mi­nar o tipo de um objeto no tempo de execução. Para dis­tin­guir vários tipos possíveis entre si, uma estrutura if-elif-else deve ser usada:

# Determinar o tipo do objeto
if type(obj) é int:
    print("Int")
elif type(obj) é float:
    print("Float")
elif type(obj) é ...:
    print("...")
else:
    print("Algo diferente")
Python

A partir da versão Python 3.10, no entanto, a instrução match-case é suportada. Ela é capaz de re­co­nhe­cer tipos sem chamar a função type().

Em um bloco case, funções cons­tru­to­ras como int(obj) ou str(obj) podem ser usadas para fazer o bloco cor­res­pon­der (match), se o objeto tiver o res­pec­tivo tipo.

# Exemplo de objeto
obj = 42
# Determinar tipo de objeto
match obj:
    case int(obj):
        print(f"{obj} é `int`")
    case float(obj):
        print(f"{obj} é `float`")
    case _:
        print(f"{obj} é outra coisa")
Python
Dica

Se você está começando agora nessa linguagem de pro­gra­ma­ção, acesse o nosso tutorial sobre Python. Nosso artigo sobre ope­ra­do­res em Python também pode lhe ser útil.

Ir para o menu principal