Tipado básico en Python

Tipado básico en Python

Tabla de Contenido

Note

Este artículo es parte de una serie que explica el tipado en Python. A continuación, puedes ver la recopilación de todos los posts de la serie.

Ver serie

Agregar tipos en Python es muy sencillo y tiene una sintaxis similar a otros lenguajes como Typescript. No es obligatorio aplicar tipado en cada pieza de código, lo que permite agregarlo de manera gradual. Además, agregar o no tipos no afectará el comportamiento del código.

Info

La posibilidad de agregar tipado en Python está disponible desde la versión 3.5. Desde entonces, se han añadido nuevas características y mejoras.

Tipos Buitl-in in Python

Los tipos built-in son aquellos que vienen por defecto en Python, como str, int, float, bool, bytes, None, list, dict, tuple, set, entre otros.

Para agregar tipado a una variable, simplemente añade : después del nombre de la variable y luego especifica el tipo de dato. La sintaxis es:

<variable>: <type> = <value>

Ejemplo:

n: int = 1
f: float = 10.0
c: complex = 1 + 2j
b: bool = True
s: bytes = b'bytes'
t: str = "hello world"
v: None = None

En el anterior ejemplo estamos definiendo que cada una de las variables solo van a manejar un tipo de datos a lo largo de vida en el programa.

Note

Recuerda que el agregar el tipo de dato no afecta el comportamiento del código, es solo una ayuda para el programador, analizadores de código estáticos e IDEs.

Tipado en colecciones

Para colecciones como list, dict, tuple, set, la sintaxis es similar a la de las variables simples. salvo que podemos definir o nor el tipo de variable que cada variable va a contener. es decir que tenemos dos tipos de sintaxis que podemos utilizar.

  • <variable>: <collection> = <value>

  • <variable>: <collection>[<type>...] = <value>

En la primera opción estamos definiendo que la variable va a ser de tipo list, dict, tuple, set y en la segunda opción estamos definiendo que la variable va a ser de tipo list, dict, tuple, set y que va a contener un tipo de dato especifico. Veamos como se aplica esto en algunos ejemplos, para ello es importante tener en cuenta la versión de Python que estás utilizando.

  • Python 3.5 a 3.8: Es necesario importar los tipos de la librería typing:

    from typing import List, Set, Tuple, Dict
    
    l: List = [1, 2, 3, 4]
    s: Set[str] = {"hello", "world"}
    t: Tuple[int, str, bool] = (10, "Python", True)
    d: Dict[str, bool] = {"active": True, "admin": False}
    
  • Python 3.9 y posteriores: Puedes utilizar la sintaxis estándar sin importar typing:

    l: list = [1, 2, 3, 4]
    s: set[str] = {"hello", "world"}
    t: tuple[int, str, bool] = (10, "Python", True)
    d: dict[str, bool] = {"active": True, "admin": False}
    

En los ejemplos anteriores podemos observar que estamos definiendo un tipo de colección diferente por cada varibale y cabe destacar que en el caso de las colecciones podemos definir el tipo de dato que va a contener cada una de las variables, debes tener en cuenta que:

  • para list y set se utiliza el tipo de dato que va a contener entre corchetes [].
  • para tuple se define el tipo de dato y la posición dentro de la tupla entre corchetes [], es decir que en el ejemplo se espera que sea una tupla de tres elementos que estaran en el siguiente orden int, str, bool.
  • para dict se define el tipo de dato que va a contener la llave y el valor entre corchetes [], es decir que en el ejemplo se espera que sea un diccionario con llaves de tipo str y valores de tipo bool.

Combinación de Tipos en Python

En algunos casos, es necesario que las variables puedan contener más de un tipo de dato o incluso que puedan ser opcionales. Para ello se han definido diversas estrategias para alcanzar esta funcionalidad

Definir Más de un Tipo

Utiliza el carácter | para definir más de un tipo de dato en una variable, este carácter actúa como un OR lógico:

a: int | str = 1
b: int | str = "one"

Para versiones anteriores a Python 3.9, importa Union de typing:

from typing import Union

a: Union[int, str] = 1
b: Union[int, str] = "one"

Valores Opcionales o None

Para definir que un valor es opcional, añade None como parte de los tipos posibles:

a: int | None = 1
b: int | None = None

Para versiones anteriores a Python 3.9, utiliza Optional o Union:

# Opción 1
from typing import Optional

a: Optional[int] = 1

# Opción 2
from typing import Union

a: Union[int, None] = None

Definir Valores Fijos

Si deseas restringir los valores que puede tomar una variable, usa Literal de typing:

from typing import Literal

cards: Literal["clubs", "diamonds", "hearts", "spades"]
cards = "clubs"

Definir Tipos Personalizados

EN Python asi como con las variables es posible definir tipos personalizados, para simplificar la lectura del código o incluso para darle un mejor entendimiento al código. en la siguiente pieza de código podemos ver esta funcionalidad.

from typing import Literal

UserType = Literal["admin", "user"]
ID = int | str
PersonalData = dict[str, str | bool| float | None]

User = tuple[ID, PersonalData, UserType]
UserUgly = tuple[int | str, dict[str, str | bool| float | None], Literal["admin", "user"]] 

Como podemos observa en el ejemplo anterior estamos separando nuestra definición de tipos en otros tipos para facilitar la lectura de nuestro código, en el caso de User y UserUgly estamos definiendo un tipo de dato que va a ser una tupla que va a contener un ID, PersonalData y UserType y en el caso de UserUgly estamos definiendo el mismo tipo de dato pero de una manera menos legible.

si escribieramos el mismo código para versiones anteriores a Python 3.9, el código se vería de la siguiente manera:

from typing import Literal, Union, Optional

UserType = Literal["admin", "user"]
ID = Union[int, str]
PersonalData = dict[str, Optional[str, bool, float]]

User = tuple[ID, PersonalData, UserType]

Datos IO en Python

Cuando trabajes con datos de entrada/salida, como la lectura de archivos, usa el tipo IO de typing:

from typing import IO

text_file: IO[str]  # text, json, xml, html...
bin_file: IO[bytes] # jpeg, png, pdf, mp3...

El tipo IO es un tipo genérico que se utiliza para representar objetos que son streams de entrada o salida, como archivos y sockets, y solo admite tipos de datos str y bytes.

Info

En este artículo, hemos cubierto las nociones básicas sobre cómo agregar tipos a tus variables en Python. En el próximo artículo, exploraremos cómo agregar tipos a funciones y métodos.