Python Typing: Mejora la legibilidad del código

PythonBeginner
Practicar Ahora

Introducción

En este tutorial, aprenderá a usar el módulo typing de Python para agregar pistas de tipos a su código. Las pistas de tipos ayudan a hacer que su código sea más legible y mantenible al indicar explícitamente los tipos de entrada y salida esperados de sus funciones.

Este es un Guided Lab, que proporciona instrucciones paso a paso para ayudarte a aprender y practicar. Sigue las instrucciones cuidadosamente para completar cada paso y obtener experiencia práctica. Los datos históricos muestran que este es un laboratorio de nivel intermedio con una tasa de finalización del 58%. Ha recibido una tasa de reseñas positivas del 88% por parte de los estudiantes.

Tipos básicos

Las pistas de tipos son una característica introducida en Python 3.5, y el módulo typing se agregó en Python 3.5.2 para proporcionar un conjunto estándar de anotaciones de tipos. Importe los tipos relevantes del módulo typing para comenzar a usar pistas de tipos.

from typing import List, Tuple, Dict

Las pistas de tipos para los tipos básicos son directas. Simplemente use el tipo en sí mismo como pista.

Abra la shell de Python escribiendo el siguiente comando en la terminal.

python3
  1. Defina una variable de tipo int, asígnale un valor e imprímala.
age: int = 25
print(age) #Output: 25
  1. Defina una variable de tipo float, asígnale un valor e imprímala.
temperature: float = 98.6
print(temperature) ## Output: 98.6
  1. Defina una variable de tipo bool, asígnale un valor e imprímala.
is_raining: bool = True
print(is_raining) ## Output: True
  1. Defina una variable de tipo str, asígnale un valor e imprímala.
def greet(name: str) -> str:
    return f"Hello, {name}!"

print(greet("Alice")) ## Output: Hello, Alice!
  1. Defina una función que tome dos argumentos de tipo int, los multiplique y devuelva el resultado como un int.
def multiply(x: int, y: int) -> int:
    return x * y

result = multiply(5, 10)
print(result) ## Output: 50

Contenedores y Genéricos

Las pistas de tipos para los tipos de contenedor (como listas, diccionarios y conjuntos) pueden ser más específicas usando genéricos.

Consejos: Los experimentos con números de serie 1-3 se pueden implementar en la shell de Python, y los experimentos con número de serie 4 se implementan en WebIDE.

  1. Defina una variable de tipo List[int], asígnele algunos valores e imprímala.
from typing import List
numbers: List[int] = [1, 2, 3, 4, 5]
print(numbers) ## Output: [1, 2, 3, 4, 5]
  1. Defina una variable de tipo Dict[str, int], asígnele algunos pares clave-valor e imprímala.
from typing import Dict
ages: Dict[str, int] = {"Alice": 25, "Bob": 30, "Charlie": 35}
print(ages) ## Output: {'Alice': 25, 'Bob': 30, 'Charlie': 35}
  1. Defina una variable de tipo Tuple[str, int, float], asígnele algunos valores e imprímala.
from typing import Tuple
person: Tuple[str, int, float] = ("Alice", 25, 5.7)
print(person) ## Output: ('Alice', 25, 5.7)
  1. Defina una función que tome una lista de enteros como argumento y devuelva el resultado como un nuevo conjunto de enteros.

Cree un Proyecto llamado list_to_set.py en WebIDE y escriba el siguiente contenido.

from typing import List, Set

def get_unique_elements(elements: List[int]) -> Set[int]:
    return set(elements)

numbers = [1, 2, 2, 3, 4, 4, 4, 5]
unique_numbers = get_unique_elements(numbers)
print(unique_numbers)  ## Output: {1, 2, 3, 4, 5}

Use el siguiente comando para ejecutar el script.

python list_to_set.py

Tipos definidos por el usuario

También puede usar tipos y clases personalizados como pistas de tipos.

Consejos: Este experimento se implementa en WebIDE.

  1. Defina una clase Person con atributos tipados name (str) y age (int) y un método get_summary que devuelva una cadena que resume el nombre y la edad de la persona.

Cree un Proyecto llamado str_and_int_to_str.py en WebIDE y escriba el siguiente contenido.

class Person:
    def __init__(self, name: str, age: int):
        self.name = name
        self.age = age
    def get_summary(self) -> str:
        return f"{self.name} is {self.age} years old."

person1 = Person("Alice", 25)
print(person1.get_summary()) ## Output: Alice is 25 years old.

Use el siguiente comando para ejecutar el script.

python str_and_int_to_str.py
  1. Defina una clase Point con atributos tipados x e y, ambos de tipo float y un método distance que tome otro punto como argumento y devuelva la distancia entre los dos puntos.

Cree un Proyecto llamado other_to_float.py en WebIDE y escriba el siguiente contenido.

import math

class Point:
    def __init__(self, x: float, y: float):
        self.x = x
        self.y = y
    def distance(self, other: "Point") -> float:
        return math.sqrt((self.x - other.x)**2 + (self.y - other.y)**2)

point1 = Point(0, 0)
point2 = Point(3, 4)
print(point1.distance(point2)) ## Output: 5.0

Use el siguiente comando para ejecutar el script.

python other_to_float.py

Alias de tipo

Los alias de tipos pueden crear pistas de tipos más legibles, especialmente para tipos complejos.

Cree un Proyecto llamado type_aliases.py en WebIDE y escriba el siguiente contenido.

from typing import List, Tuple

Coordinate = Tuple[float, float]
Path = List[Coordinate]

def get_distance(coord1: Coordinate, coord2: Coordinate) -> float:
    return ((coord1[0] - coord2[0])**2 + (coord1[1] - coord2[1])**2)**0.5

start = (0, 0)
end = (3, 4)
print(get_distance(start, end))  ## Output: 5.0

Use el siguiente comando para ejecutar el script.

python type_aliases.py

Opcional y Ninguno

El tipo Optional se puede usar cuando un valor puede ser de un tipo específico o None.

  1. Defina una función que tome un argumento int opcional, lo multiplique por 2 si no es None y devuelva el resultado como un int o None si la entrada era None.

Cree un Proyecto llamado option_and_none_1.py en WebIDE y escriba el siguiente contenido.

from typing import Optional

def double_or_none(number: Optional[int]) -> Optional[int]:
    if number is not None:
        return number * 2
    else:
        return None

result1 = double_or_none(5)
result2 = double_or_none(None)
print(result1, result2) ## Output: 10 None

Use el siguiente comando para ejecutar el script.

python option_and_none_1.py
  1. Defina una clase Person con un atributo tipado address, que puede ser una cadena de dirección válida o None.

Cree un Proyecto llamado option_and_none_2.py en WebIDE y escriba el siguiente contenido.

from typing import Optional

class Person:
    def __init__(self, name: str, age: int, address: Optional[str]):
        self.name = name
        self.age = age
        self.address = address

person1 = Person("Alice", 25, "123 Main St")
person2 = Person("Bob", 30, None)
print(person1.name, person1.age, person1.address) ## Output: Alice 25 123 Main St
print(person2.name, person2.age, person2.address) ## Output: Bob 30 None

Use el siguiente comando para ejecutar el script.

python option_and_none_2.py

Callable

El tipo Callable se utiliza para especificar el tipo de una función o método.

Cree un Proyecto llamado callable.py en WebIDE y escriba el siguiente contenido.

from typing import Callable

def apply_function(value: int, func: Callable[[int], int]) -> int:
    return func(value)

def double(x: int) -> int:
    return x * 2

print(apply_function(5, double))  ## Output: 10

Use el siguiente comando para ejecutar el script.

python callable.py

Typeddict

TypedDict te permite crear diccionarios personalizados con claves y tipos de valores específicos.

Consejos: TypedDict se introdujo en Python 3.8, por lo que debes estar ejecutando Python 3.8 o posterior para poder usarlo.

Aquí hay un ejemplo:

Crea un Proyecto llamado typeddict.py en WebIDE y escribe el siguiente contenido.

from typing import TypedDict

class PersonInfo(TypedDict):
    name: str
    age: int

def greet(person: PersonInfo) -> str:
    return f"Hello, {person['name']}! You are {person['age']} years old."

alice_info: PersonInfo = {"name": "Alice", "age": 30}
print(greet(alice_info))  ## Output: Hello, Alice! You are 30 years old.

Usa el siguiente comando para ejecutar el script.

python typeddict.py

Newtype

NewType es una pista de tipo del módulo typing en Python que te permite crear un nuevo tipo que es solo un envoltorio alrededor de un tipo existente. Esto puede ser útil para agregar más significado semántico a variables y argumentos de función.

Aquí hay un ejemplo:

Crea un Proyecto llamado newtype.py en WebIDE y escribe el siguiente contenido.

Luego ejecuta el siguiente script de python.

from typing import NewType

UserId = NewType("UserId", int)
OrderId = NewType("OrderId", int)

def get_order(order_id: OrderId) -> str:
    return f"Order with ID: {order_id}"

order_id = OrderId(123)
user_id = UserId(123)

print(get_order(order_id))  ## Output: Order with ID: 123

Usa el siguiente comando para ejecutar el script.

python newtype.py

Verificación de Tipo Estático

En Python, la verificación de tipos estáticos se puede realizar utilizando pistas de tipo y un verificador de tipos estáticos como mypy. Las pistas de tipo indican los tipos esperados de variables, argumentos de función y valores de retorno. Aquí hay un ejemplo:

Primero, instala mypy.

pip install mypy

Aquí hay un ejemplo:

Crea un Proyecto llamado mypy.py en WebIDE y escribe el siguiente contenido.

def add_numbers(x: int, y: int) -> int:
    return x + y

result = add_numbers(2, 3)
print(result)

Luego ejecuta mypy en tu script.

mypy mypy.py

Esto te dará retroalimentación sobre cualquier inconsistencia de tipos encontrada en tu código.

Resumen

¡Eso es todo! Ahora sabes cómo usar el módulo typing de Python para agregar pistas de tipo a tu código. Las pistas de tipo pueden mejorar significativamente la legibilidad y la mantenibilidad del código, lo que hace que sea más fácil trabajar con bases de código más grandes y colaborar con otros.