O que é a função type() em Python?

A função type() em Python é uma função básica para a manipulação de tipos. Como parte da implementaçã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 diferentes:

  1. Para obter o tipo de um objeto Python.
  2. Para criar dinamicamente uma nova classe.

Vamos considerar o primeiro caso, que ocorre com muito mais frequência no uso diário.

Obter tipo de objeto com type()

Python é uma linguagem dinâmica. Isso significa que seus tipos são determinados somente durante o tempo de execução, sendo vinculados a valores em vez de a variáveis. Dessa circunstância surge a necessidade de determinar 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:

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 representação textual do objeto retornado mencionará “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 corresponde à classe dele. Assim, chamar a função type() é geralmente equivalente 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 argumentos, 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 semelhante à palavra-chave class. O código type = type("Type", bases, dict) pode ser pensado como uma definição de classe equivalente:

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 argumentos:

name bases dict **kwds
Nome do novo tipo como string Tupla com classes base Dicionário com atributos da nova classe Argumentos adicionais para instanciação da metaclasse
Dica

Com o Deploy Now da IONOS, você pode implantar sites e aplicativos pelo GitHub.

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

Se você usar a função type() para determinar o tipo de um objeto, o valor retornado não será uma string, mas um objeto independente:

# 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 retornados pela função type() para objetos de diferentes 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() Representaçã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 representa 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 continuado indefinidamente, como uma cobra mordendo o próprio rabo:

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

Para esclarecer qualquer confusão, é essencial que você se aprofunde no sistema de programação orientada a objetos (OOP) de Python. O objeto embutido type em Python representa uma metaclasse. Uma metaclasse se comporta, em relação a uma classe, como uma classe se comporta em relação a um objeto. Em outras palavras, uma metaclasse funciona como um modelo para uma classe, enquanto uma classe funciona como um modelo para um objeto:

Modelo Instância
Classe Objeto
Metaclasse 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 funcionalidade é valiosa, porque o Python é uma linguagem dinamicamente tipada. Em contraste, linguagens estaticamente tipadas, como Java, exigem que os tipos das variáveis sejam declarados, 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 simplesmente nomes que se referem a valores tipados. A qualquer momento durante a execução do código, um nome pode ser referenciado a um valor de tipo diferente. Portanto, para determinar 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 é necessário verificar se os argumentos cumprem certos critérios. Isso inclui checar se os argumentos estão dentro de certos limites ou confirmar que são de tipos adequados. Ao realizar essas verificações, você pode evitar potenciais erros de tempo de execução.

Vamos ilustrar o uso da função type() com um exemplo. Definiremos uma função que soma uma lista de números. Para que ela funcione, precisamos 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 linguagens interpretadas, como Python, é a execução interativa de códigos no REPL (Read-Eval-Print-Loop), que possibilita prototipagem 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. Descobrimos que o tipo não corresponde às nossas expectativas e usamos a função type() em Python para exibir o tipo. Como se constata, escrevemos acidentalmente o valor booleano entre aspas – um erro comum, especialmente entre os iniciantes:

# 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 dinamicamente com a função type()

Como já demonstrado, classes em Python podem ser criadas dinamicamente, ou seja, no tempo de execução, pela função type(). Isso é útil, entre outras coisas, em famílias de classes. Vamos demonstrar o conceito de famílias de classes com um exemplo que usa tags HTML. Primeiramente, criamos uma classe base Tag, para que objetos dessa classe possam se representar 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 especializar a classe base Tag, por herança, para tags HTML específicas, 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. Dicionário com o nome da classe e as entradas adicionais, se necessário. Essas entradas também podem ser funções. Posteriormente, instanciamos uma tag p e verificamos se a representação funciona corretamente:

# 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 capacidade 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 compreensã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 subclasses relacionadas. Demonstramos essa abordagem usando o exemplo mais complexo de definição de classes para modelar cartas de baralho. Primeiramente, definimos uma superclasse, 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 subclasses 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 individuais podem ser instanciadas:

# 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. Felizmente, para essas situações, a linguagem oferece algumas soluções alternativas. Vamos analisá-las.

Quebrar hierarquias de herança com isinstance()

type() somente determina o tipo real de um objeto em Python, ignorando a hierarquia de herança. Vamos ilustrar esse dilema reutilizando 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 corretamente o polimorfismo subjacente, 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

Simplificar detecção de tipo de objetos com match-case

Como já demonstrado, a função type() é frequentemente usada para determinar o tipo de um objeto no tempo de execução. Para distinguir 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 reconhecer tipos sem chamar a função type().

Em um bloco case, funções construtoras como int(obj) ou str(obj) podem ser usadas para fazer o bloco corresponder (match), se o objeto tiver o respectivo 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 programação, acesse o nosso tutorial sobre Python. Nosso artigo sobre operadores em Python também pode lhe ser útil.

Este artigo foi útil?
Para melhorar a sua experiência, este site usa cookies. Ao acessar o nosso site, você concorda com nosso uso de cookies. Mais informações
Page top