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:
- Para obter o tipo de um objeto Python.
- 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
PythonSe 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)
PythonO 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__
PythonCriar 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)
PythonNessa 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>
PythonAbaixo 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 |
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
PythonVamos 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)}")
PythonChamada 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))
PythonIsso 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
PythonAssim, 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
PythonPara 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;
JavaPor 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
PythonVerificar 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')
PythonDepurar 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
PythonCriar 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}>"
PythonPara 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-
Nome da nova classe como string.
-
Tupla com classes base.Python permite heranças múltiplas; para derivação de apenas uma classe, usamos a notação
(NomeClasse,)
. -
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) == '<p>Olá, mundo</p>'
PythonO mesmo efeito pode ser alcançado por definição de classe análoga:
# Criar classe `P`
class P(Tag):
name = 'p'
PythonComo 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]
PythonComo 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}"
PythonEm 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'})
PythonAgora, as cartas individuais podem ser instanciadas:
# Instanciar um 7 de Espadas
carta = Espadas(7)
# Mostrar que funcionou
assert str(carta) == '7 de Espadas'
PythonQuais 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
PythonPara 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)
PythonSimplificar 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")
PythonA 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")
PythonSe 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.