Qué hay de nuevo

Python recientemente ha venido anunciando algunas características muy interesantes en sus lanzamientos actuales e incluso a futuro, en este artículo mencionaré algunos de los que más me han gustado y el porqué, adicionando también un poco de código que nunca esta de mas

python 3.9

type hinting "nativo", los types hinting es una forma práctica de utilizar tipado estático en python sin embargo para utilizar tipos de datos como list y dict se debía utilizar esto generaba duplicidad y ademas generaba un poco de confusión con los nuevos programadores que lo querían usar (los que llegaron a python por su tipado dinámico no tienen que preocuparse, no será obligatorio usarlo o  si? ver Figura 1)

Figura 1: Tipado dinamico vs tipado estático obtenido de https://www.reddit.com/r/ProgrammerHumor/comments/a1hghl/dynamic_vs_static_typing/

podemos ver en el siguiente código como es la nueva implementación del list agregado de manera nativa

class Book:
    def __init__(self,title:str) -> None:
        pass
    
def get_books()->list[Book]:
    books = [Book("Misery"), Book("A song of ice and fire")]
    return books

print(get_books())

como debía trabajarse en versiones < 3.9

from typing import List
class Book:
    def __init__(self,title:str) -> None:
        pass
    
def get_books()->List[Book]:
    books = [Book("Misery"), Book("A song of ice and fire")]
    return books

print(get_books())

como se aprecia utilizamos List del módulo typing que es una versión genérica de list adicionalmente mypy ya tiene el soporte para poder realizar validaciones de los tipos estáticos (también soporta algunos tipos como List y Dict pero los trata como legacy) como se aprecia en la Figura 2 donde cambio el tipo de return a un str para validarlo como se aprecia en el código

def get_books()->list[Book]:
    books = [Book(title="Misery"), Book(title="A song of ice and fire")]
    return "test"
Figura 2:  Soporte de mypy para typing nativo en python

python 3.10

Pattern Matching Esta es una feature que realmente me interesa usar en producción, el release oficial está para octubre de este año. Cuando tenía que trabajar en java y python al mismo tiempo a veces extrañaba usar el switch case, este es una versión de este concepto pero con muchisimas mas mejoras, de hecho en varios lenguajes como scala y rust ya se implementa y en python lleva un buen tiempo ya debatiéndose la implementación, el concepto muy resumido es hacer match de un variable por medio de un patrón dado, a diferencia de switch que generalmente es una simple comparación, a continuación tenemos un ejemplo sencillo


def http_error(status):
    match status:
        case 400:
            return "Bad request"
        case 404:
            return "Not found"
        case 418:
            return "I'm a teapot"
        case _:
            return "Something's wrong with the Internet"

http_error()

podemos ver un ejemplo un poco más elaborado donde aplicamos varios conceptos


def validate_user(user_info:tuple):
    match user_info:
        case ("",""):
            print("not enough information is being provided")
        case (name,""):
            print("do not you have a last name?")
        case ("", last_name):
            print("do not you have a name?")
        case (name, last_name):
            print(f"Success {name} {last_name}")
        case _:
            raise ValueError("Not  User")

validate_user(("jairo","andres"))

la salida por consola sería la siguiente

Success jairo andres

en el código la función match lo que realiza es algo llamado un desempaquetamiento de variable y guarda su valor para trabajar en el contexto del case, pero aquí viene lo interesante y es que en el caso anterior al tener una variable tipo tupla la desempaqueta y permite trabajar con los valores que vienen en sus posiciones

(name,last_name) = user_info 

con ello aquí entra la diferencia entre un switch case que es algo más superficial y el match pattern que permite validar situaciones más elaboradas

python 3.11

tracebacks mejorados, actualmente python tiene para mi un pequeño inconveniente con el tema de la trazabilidad de los errores y es que en los logs tanto como en los errores que se muestran en consola la línea donde ocurre el error te lo marca pero.. bueno una línea de código puede tener varias instrucciones, al ser python un lenguaje de tipado dinámico a veces esta línea puede ser difícil de leer, veamos un ejemplo actual

def calculate(a,b,c,d,e,f):
    result = (a/b/c)*(d/e/f)

calculate(1,2,3,4,0,5)

si ejecutamos tendremos un error similar al siguiente

Traceback (most recent call last):
  File "main.py", line 12, in <module>
    calculate(1,2,0,4,2,5)
  File "main.py", line 10, in calculate
    result = (a/b/c)*(d/e/f)
ZeroDivisionError: division by zero

el error es claro, sin embargo no hay claridad en cual de toda la linea anterior sucede el error, es decir en cual operación exacta sucede la división por 0, con la mejora que realmente me parece super buena se vería de la siguiente el error

Traceback (most recent call last):
  File "calculation.py", line 54, in <module>
    result = (a / b / c) * (d / e / f)
              ~~~~~~^~~
ZeroDivisionError: division by zero

aquí nos indica que el error ocurre en la división de la variable c por lo tanto ya se puede encontrar el error de una manera más exacta, funciona muy bien también con los diccionarios

Traceback (most recent call last):
  File "test.py", line 2, in <module>
    x['a']['b']['c']['d'] = 1
    ~~~~~~~~~~~^^^^^
TypeError: 'NoneType' object is not subscriptable

En el código anterior es un diccionario que en su clave 'c' está devolviendo none entonces se puede verificar si esta mal la key o es que en su valor tiene None, pero ya con esto se tiene más claro donde ocurre y no un error más genérico de que algún valor es none pero no se sabe exactamente cual. Aunque aún debemos esperar ya que la fecha de lanzamiento para este release esta dadas para 2022

Conclusiones

Actualmente python en mi opinión viene haciendo cambios que están interesantes y que complementan bastante a los programadores, de alguna manera están escuchando a la comunidad y sus requerimientos hay algunas promesas para mejoras a futuro en cuanto a rendimiento lo cual genera también un "hype" sobre lo que se viene, por ahora según un tweet de su propio creador podemos tener certeza de que si hay un cambio de un python 3 a un 4 no será tan conflictivo como lo fue de la 2 ala 3