La función type() es una función básica de Python para trabajar con tipos. Como parte de la im­ple­me­n­ta­ción de Python, pertenece al núcleo del lenguaje.

¿Para qué sirve la función type() en Python?

La función type() se utiliza en Python con dos objetivos bastante di­fe­re­n­tes:

  1. De­te­r­mi­nar el tipo de un objeto
  2. Crear di­ná­mi­ca­me­n­te un nuevo tipo

Veamos primero el primer caso, que es mucho más útil en el uso cotidiano.

De­te­r­mi­nar el tipo de un objeto con type()

Python es un leguaje de tipado dinámico. Esto significa que los tipos se de­te­r­mi­nan en tiempo de ejecución y están ligados a valores en lugar de a variables. Debido a esta ca­ra­c­te­rí­s­ti­ca, es necesario de­te­r­mi­nar el tipo de un objeto en tiempo de ejecución.

Llamamos a la función type() de Python y le pasamos un objeto como único parámetro. Como resultado obtenemos el tipo del objeto, por ejemplo into str:

# Type of `42` is `int`
assert type(42) == int
# Type of `str(42)` is `str`
assert type(str(42)) == str
Python

Si llamamos a la función type() en el REPL de Python, la re­pre­se­n­ta­ción textual contiene la palabra “class” en lugar de “type”:

# Returns "<class 'int'>" inside REPL
type(42)
Python

Aunque al principio puede parecer confuso, tiene sentido. Python sigue el principio de “todo es un objeto”. En Python, el tipo de un objeto co­rre­s­po­n­de a su clase. Por lo tanto, llamar a la función type() es equi­va­le­n­te a acceder al atributo __class__.

# Should hold in most cases
assert type(obj) is obj.__class__
Python

Crear un nuevo tipo con type()

Veamos ahora el segundo uso posible de la función type(). Si se llama con tres ar­gu­me­n­tos, la función nos permite crear di­ná­mi­ca­me­n­te un nuevo tipo:

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

En esta forma, la función type() de Python funciona de forma análoga a la palabra clave class. El código Type = type(“Type”, bases, dict) equivale apro­xi­ma­da­me­n­te a la siguiente de­fi­ni­ción de clase:

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

A co­n­ti­nua­ción, te mostramos algunos ejemplos concretos del uso de la función type() de Python para crear nuevos tipos. Antes, sin embargo, te pre­se­n­ta­mos una de­s­cri­p­ción general de los ar­gu­me­n­tos:

name bases dict **kwds
Nombre del nuevo tipo como cadena de texto Tupla con clases de base Di­c­cio­na­rio con los atributos de la nueva clase Otros ar­gu­me­n­tos para la in­s­ta­la­ción de la metaclase
Consejo

Con Deploy Now de IONOS puedes im­ple­me­n­tar tu página web o apli­ca­ción a través de GitHub.

¿Cómo funciona la función type() de Python?

Cuando se utiliza la función type() para de­te­r­mi­nar el tipo de un objeto, el valor de retorno no es una cadena, sino un objeto in­de­pe­n­die­n­te:

# Value returned by `type(42)` is not a string
assert type(42) != 'int'
# We get back an object named `int`
assert type(42) == int
Python

Veamos algunos ejemplos de valores de retorno de la función type() para objetos de tipos co­m­ple­ta­me­n­te di­fe­re­n­tes:

# Python objects of different types
different_objs = None, True, 42, 'John', ('Walter', 'White'), ...
# Print out the type of each object
for obj in different_objs:
    print(f"{obj}: {type(obj)}")
Python
Llamada a type() Re­pre­se­n­ta­ción 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'>

Es posible que te preguntes cuál es el tipo del objeto devuelto por type(). Hagamos la prueba. Llamamos a la función type() de Python y le pasamos el valor de retorno de otra llamada a type():

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

Vemos que, además de la función type() in­co­r­po­ra­da en Python, existe el tipo type con el mismo nombre. Este es el tipo de todos los demás tipos en Python, como mostramos en este ejemplo:

# DifferentPython objects
different_objs = None, True, 42, 'John', ('Walter', 'White'), ...
# Check the type of each object's type
for obj in different_objs:
    # Show that the type's type is always `type`
    assert type(type(obj)) is type
Python

El tipo de cada tipo en Python es, de hecho, type. Puede sonar confuso, y aún hay más: el tipo del objeto type es también type. Esto puede continuar in­de­fi­ni­da­me­n­te:

# It's `type` all the way down
assert type(type(type(type))) is type
Python

Para aclarar la confusión, se necesita una co­m­pre­n­sión más profunda del sistema de pro­gra­ma­ción orientada a objetos de Python. El objeto in­co­r­po­ra­do type de Python re­pre­se­n­ta una metaclase. Una metaclase se comporta con una clase como una clase se comporta con un objeto. En otras palabras, una metaclase es una plantilla para una clase, mientras que una clase es una plantilla para un objeto:

Plantilla Instancia
Clase Objeto
Metaclase Clase
Ejemplo: type int, str etc.
Ejemplo:int 42
Ejemplo: str “Walter White”

¿Cómo se utiliza la función type() en Python?

No­r­ma­l­me­n­te, la función type() de Python se utiliza para obtener el tipo de un objeto en tiempo de ejecución. Esto es útil porque Python es un lenguaje de tipado dinámico. En un lenguaje de tipado estático como Java, un tipo está ligado a una variable por de­cla­ra­ción y no puede ser cambiado en tiempo de ejecución:

// Declare variable as `boolean`
boolean answer;
// Attempting to assign `int` value
// Throws type error
answer = 42;
Java

Por el contrario, las variables en Python son si­m­ple­me­n­te nombres que hacen re­fe­re­n­cia a valores tipados. En cualquier momento durante la ejecución del código, un nombre puede referirse a un valor con un tipo diferente. Para de­te­r­mi­nar el tipo de una variable Python en tiempo de ejecución, ne­ce­si­ta­mos la función type():

# Assign boolean value
answer = True
# Show that type is `bool`
assert type(answer) is bool
# Reassign integer value
answer = 42
# Show that type is now `int`
assert type(answer) is int
Python

Co­m­pro­ba­ción del tipo de ar­gu­me­n­tos de una función en Python

Al definir una función, a menudo es necesario comprobar que los ar­gu­me­n­tos cumplen de­te­r­mi­na­dos criterios. Por ejemplo, un argumento solo puede en­co­n­trar­se dentro de ciertos límites o solo se admiten ar­gu­me­n­tos de tipos adecuados. Así se evitan errores en tiempo de ejecución.

Veamos un ejemplo de uso de la función type(). Definimos una función que suma una lista de números. Para que funcione, ne­ce­si­ta­mos ase­gu­rar­nos de que cada argumento es realmente un número. Uti­li­za­re­mos type() dentro de una sentencia assert:

# Function to add up numeric arguments
def add_numbers(*args):
    result = 0
    # Check each argument
    for arg in args:
        # Abort with error message if argument is not an `int` or `float`
        assert type(arg) in (int, float), f"Argument `{arg}` is not a number"
        # Add argument's value to total
        result += arg
    return result
# Show that it works for numbers
assert add_numbers(35, 7) == 42
# The following will fail
add_numbers(29, 'thirteen')
Python

De­pu­ra­ción en Python REPL con la función type()

Una de las ventajas de utilizar un lenguaje in­te­r­pre­ta­do como Python es la ejecución in­ter­ac­ti­va de código en el REPL (Read Eval Print Loop). Este enfoque permite la creación rápida de pro­to­ti­pos y la de­pu­ra­ción directa mediante la in­s­pe­c­ción de los objetos en memoria.

Ima­gi­ne­mos el siguiente escenario: nuestro código contiene una variable answer que se supone que contiene un valor booleano. De­s­cu­bri­mos que el tipo no coincide con lo que es­pe­rá­ba­mos y uti­li­za­mos la función type() de Python para obtener el tipo real. Resulta que ac­ci­de­n­ta­l­me­n­te es­cri­bi­mos el valor booleano entre comillas. Es un error común, es­pe­cia­l­me­n­te entre pri­n­ci­pia­n­tes:

# Accidentally set to string
answer = 'False'
# Assertion will fail
assert type(answer) is bool
# Correct to boolean value
answer = False
# Now assertion holds
assert type(answer) is bool
Python

Creación dinámica de clases Python con la función type()

Como hemos visto, las clases Python pueden crearse di­ná­mi­ca­me­n­te, es decir, en tiempo de ejecución, con la función type(). Esto es útil, entre otras cosas, para las familias de clases, que mostramos con el ejemplo de las etiquetas HTML. En primer lugar, creamos una clase base tag, cuyos objetos pueden re­pre­se­n­tar­se a sí mismos como código HTML:

# Class representing HTML tag
class Tag:
    # Initialize HTML tag with contents
    def __init__(self, *args):
        # Join contents of tag
        self.content = "".join([arg.__str__() for arg in args])
    # String representation returns HTML
    def __str__(self):
        return f"<{self.name}>{self.content}</{self.name}>"
Python

A co­n­ti­nua­ción, es­pe­cia­li­za­re­mos la clase base mediante herencia para los tags es­pe­cí­fi­cos como <p> o <h1>. Para ello, llamamos a la función type() con tres ar­gu­me­n­tos:

# Create `P` class
P = type('P', (Tag,), {"name": 'p'})
Python
  1. Nombre de la nueva clase en forma de cadena.

  2. Tupla con las clases base.

    Python permite la herencia múltiple; para derivar de una sola clase, uti­li­za­mos la notación (ClassName,).

  3. Dict con el nombre de la clase y op­cio­na­l­me­n­te otros elementos.

    Los elementos pueden ser funciones.

A co­n­ti­nua­ción, in­s­ta­n­cia­mos una etiqueta p y co­m­pro­ba­mos que la re­pre­se­n­ta­ción funciona co­rre­c­ta­me­n­te:

# Instantiate `p` tag
greeting = P("Hello world")
assert str(greeting) == '&lt;p&gt;Hello world&lt;/p&gt;'
Python

El mismo efecto puede co­n­se­gui­r­se mediante la de­fi­ni­ción de clases análogas:

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

Como otro ejemplo, creamos clases para en­ca­be­za­dos uti­li­za­n­do type(). Dado que la creación de las clases es dinámica, podemos generar las clases para los seis niveles de en­ca­be­za­do de una vez uti­li­za­n­do una list co­m­prehe­n­sion.

h_1_to_6 = ( f"h{n}" for n in range(1, 7) )
headings = [type(heading, (Tag,), {"name": heading}) for heading in h_1_to_6]
Python

Como hemos de­mo­s­tra­do, vale la pena utilizar la función type() para crear có­mo­da­me­n­te múltiples subclases re­la­cio­na­das. Mo­s­tra­re­mos este enfoque con un ejemplo más complejo: de­fi­nie­n­do clases para modelar cartas de naipes. Primero, de­fi­ni­re­mos una su­pe­r­cla­se Card uti­li­za­n­do la palabra clave class:

# Class representing abstract playing card
class Card:
    def __init__(self, number):
        self.number = number
    # String representation
    def __str__(self):
        return f"{self.number} of {self.suite}"
Python

A co­n­ti­nua­ción, creamos subclases para los cuatro palos de cartas uti­li­za­n­do type():

# Create concrete types for each suite
Clubs = type('Clubs', (Card,), {'suite': 'Clubs'})
Diamonds = type('Diamonds', (Card,), {'suite': 'Diamonds'})
Hearts = type('Hearts', (Card,), {'suite': 'Hearts'})
Spades = type('Spades', (Card,), {'suite': 'Spades'})
Python

Ahora podemos in­s­ta­n­ciar cada carta in­di­vi­dual sin problemas:

# Instantiate a 7 of Spades
card = Spades(7)
# Show that it worked
assert str(card) == '7 of Spades'
Python

¿Qué límites tiene la función type()?

La función type() de Python es útil. Sin embargo, hay algunos usos en los que la función alcanza sus límites para re­so­l­ve­r­los. Afo­r­tu­na­da­me­n­te, Python ofrece enfoques adecuados para abo­r­dar­los. Veamos algunos de ellos.

De­s­co­m­po­ner je­ra­r­quías de herencia con isi­n­s­ta­n­ce()

type() solo determina el tipo real de un objeto Python, pero ignora la jerarquía de herencia. Re­pre­se­n­ta­mos el dilema re­su­l­ta­n­te con nuestro ejemplo de naipes de la última sección. El tipo de un 7 de picas debería ser tanto “naipe” como “pica”. Sin embargo, esto no se puede de­te­r­mi­nar con type():

# Create a Seven of Spades
card = Spades(7)
# Our card is a Spade alright
assert type(card) is Spades
# But not a card??
assert type(card) is not Card
Python

Para de­s­co­m­po­ner co­rre­c­ta­me­n­te el po­li­mo­r­fi­s­mo su­b­ya­ce­n­te, hacemos uso de la función isinstance().

# Seven of Spades is a `Spade`
assert isinstance(card, Spades)
# And is also a `Card`
assert isinstance(card, Card)
Python

Si­m­pli­fi­car la detección de tipos de objetos en Python con match-case

Como hemos visto an­te­rio­r­me­n­te, la función type() se utiliza a menudo para de­te­r­mi­nar el tipo de un objeto en tiempo de ejecución. Para di­s­ti­n­guir varios tipos posibles entre sí, se puede utilizar una co­n­s­tru­c­ción if-elif-else:

# Determine type of object
if type(obj) is int:
    print("Int")
elif type(obj) is float:
    print("Float")
elif type(obj) is ...:
    print("...")
else:
    print("Something else")
Python

Desde la versión 3.10, sin embargo, Python introdujo la sentencia match-case. Esta permite, entre otras cosas, reconocer tipos sin tener que llamar a la función type().

Dentro de un bloque case se pueden utilizar funciones co­n­s­tru­c­to­ras como int(obj) o str(obj). El bloque coincide si el objeto tiene el tipo co­rre­s­po­n­die­n­te:

# Example object
obj = 42
# Determine object type
match obj:
    case int(obj):
        print(f"{obj} is `int`")
    case float(obj):
        print(f"{obj} is `float`")
    case _:
        print(f"{obj} is something else")
Python
Consejo

Para iniciarte en el lenguaje, utiliza nuestro tutorial de Python y nuestro artículo sobre ope­ra­do­res de Python.

Ir al menú principal