Principales características y mejoras en la programación de Python

Habilidades avanzadas de Python

En este tutorial, se le presentarán los últimos avances en el lenguaje de programación Python, que incluyen:

• Mensajes de error mejorados a través de rastreos más descriptivos

• Aceleración del rendimiento del código como resultado de importantes contribuciones al proyecto Faster CPython

• La integración de grupos de tareas y excepciones para una experiencia optimizada al manejar código asíncrono

• Capacidades avanzadas de escritura que aumentan la funcionalidad de escritura estática de Python

• Soporte nativo para el formato TOML en el trabajo con archivos de configuración.python programming art, mastering skill in python

Para seguir eficazmente los ejemplos presentados en este tutorial, se recomienda utilizar Python 3.11. La guía de instalación y configuración de Python 3, así como la guía sobre la instalación de una versión preliminar de Python, proporcionan varias opciones para agregar la última versión de Python a su sistema.

Además de obtener información sobre las nuevas características del lenguaje, este tutorial también ofrece orientación sobre qué tener en cuenta antes de actualizar a la última versión de Python.

 

 

 

Más seguimientos de errores descriptivos

Python es reconocido por su simplicidad y versatilidad, con su sintaxis fácil de leer y estructuras de datos robustas que lo convierten en una opción ideal para aquellos nuevos en la programación. Un desafío común que enfrentan todos, particularmente los principiantes, es la interpretación de los rastreos cuando se producen errores en Python.

En Python 3.10, hubo una mejora significativa en el sistema de mensajería de errores. Python 3.11 continúa mejorando la experiencia del desarrollador al agregar anotaciones informativas a los seguimientos. Estas anotaciones proporcionan una comprensión más clara de los mensajes de error, lo que permite una resolución más rápida de los problemas.

Para experimentar la mejora en los seguimientos, simplemente agregue el siguiente código a un archivo denominado "inverse.py

+ # Definir la función inversa

def inverso (número):

# Devuelve el resultado de 1 dividido por el número de entrada

Devolución 1 / Número

 

# Llamar a la función inversa y pasar el argumento 0

imprimir(inversa(0))

 

 

La función 'inverse()' se puede utilizar para calcular el recíproco de un número. Sin embargo, como no hay recíproco para 0, intentar ejecutar el código dará como resultado un error.

Rastreo (última llamada más reciente):

Archivo "/home/realpython/inverse.py", línea 6, en <módulo>

imprimir(inversa(0))

^^^^^^^^^^

Archivo "/home/realpython/inverse.py", línea 4, a la inversa

Devolución 1 / Número

~~^~~~~~~~

ZeroDivisionError: división por cero

```"

El resultado de ejecutar el script inverse.py da como resultado un seguimiento debido a un ZeroDivisionError que se produce cuando se intenta una división por cero. El seguimiento detalla el error, incluido el archivo en el que se produjo  (/home/realpython/inverse.py)), el número de línea (línea 6) y la llamada que causó el error (print(inverse(0))). El rastreo también muestra que el error se origina en la operación de división en la función inverse() (línea 4) con el símbolo ~~^~~~~~~~~ que indica la ubicación específica del error en el código.

Tenga en cuenta el uso de los símbolos ^ y ~ dentro del rastreo. Estos símbolos se utilizan para resaltar el código específico que está causando el error. Como es la práctica estándar cuando se trabaja con rastreos, se recomienda comenzar desde abajo y trabajar hacia arriba. En el presente ejemplo, el error es el resultado de la división 1 / número, causado por la ejecución de inverse(0) donde 0 no tiene recíproco.

 

La inclusión de estas anotaciones en los seguimientos de errores puede mejorar significativamente la experiencia de depuración, especialmente cuando el código es complejo. Las anotaciones pueden proporcionar información que antes no era posible solo con los seguimientos.

 

Para ilustrar aún más los beneficios de los rastreos mejorados, considere un escenario en el que se crea un pequeño analizador para extraer información sobre algunos programadores. Los datos se almacenan en un archivo denominado programmers.json y contiene la siguiente información:

 

# Los datos se almacenan en una lista de diccionarios, cada uno representando a un programador

# Cada programador tiene una clave de "nombre" que contiene un diccionario con "nombre" y opcionalmente "apellido" nombre

# Cada programador tiene una clave de "nacimiento" que contiene un diccionario con "año", "mes" y "día" de nacimiento

# Cada programador tiene una clave "death" que contiene un diccionario con "year", "month" y "day" of death o está configurado en "null"

[

{

"nombre": {

"primero": "Tío Barry" }},

{

"nombre": {

"primero": "Ada",

"last": "Lovelace" },

"nacimiento": {

"año": 1815 },

"muerte": {

"mes": 11,

"día": 27 }},

{

"nombre": {

"primero": "Gracia",

"last": "Hopper" },

"nacimiento": {

"año": 1906,

"mes": 12,

"día": 9 },

"muerte": {

"año": 1992,

"mes": 1,

"día": 1 } },

{

"nombre": {

"primero": "Ole-Johan",

"last": "Dahl" },

"nacimiento": {

"año": 1931,

"mes": 10,

"día": 12 },

"muerte": {

"año": 2002,

"mes": 6,

"día": 29

}

},

{

"nombre": {

"primero": "Guido",

"último": "Van Rossum"

},

"nacimiento": {

"Año": 1956,

"mes": 1,

"día": 31

},

"muerte": nulo

}

]




La información sobre los programadores en el archivo JSON es inconsistente e incompleta. Por ejemplo, la información sobre Grace Hopper y Ole-Johan Dahl está completa, pero faltan el día y el mes de nacimiento de Ada Lovelace y su año de muerte. Además, solo se registra la información de nacimiento de Guido Van Rossum, y solo se registra el nombre del tío Barry.

Para solucionar esto, creará una clase que pueda almacenar y administrar correctamente esta información. El primer paso es leer la información del archivo JSON.

# programmers.py

# Importar módulos requeridos

Importar JSON

import pathlib

# Cargar datos del archivo "programmers.json" en la variable "programmers"

programadores = json.loads(

pathlib. Path("programmers.json").read_text(encoding="utf-8")

)

El siguiente código utiliza la biblioteca pathlib para leer el contenido del archivo JSON y json para analizar el contenido en una lista de diccionarios en Python. Los datos se encapsulan en una clase de datos para una mejor organización y facilidad de uso.

# programmers.py

 

Desde DataClasses Importar DataClass

 

# Definir la clase de datos Person

@dataclass

Persona de clase:

# Definir variables de clase para almacenar el nombre y la vida útil de la persona

Nombre: Str

life_span: tupla[int, int]

 

# Definir un método de clase para convertir la información del diccionario en objeto Person

@classmethod

def from_dict(cls, info):

# Extraer el nombre y el life_span del diccionario y crear un objeto Person

return cls(

name=f"{info['name']['first']} {info['name']['last']}",

life_span=(info["nacimiento"]["año"], info["muerte"]["año"]),

)

 

 

La clase Person tiene dos atributos: nombre y life_span. La clase también contiene un método de clase denominado from_dict que sirve como un constructor conveniente para inicializar una  instancia de Person  basada en la información encontrada en un diccionario, como la almacenada en el archivo JSON. Además, hay una función que puede inicializar dos objetos Person a la vez.

def convert_pair(primero, segundo):

""Convierte dos diccionarios en dos objetos Person.

Argumentos:

first: Un diccionario que representa información sobre la primera persona.

segundo: Un diccionario que representa información sobre la segunda persona.

Devuelve:

Una tupla de dos objetos Person, uno para cada diccionario de entrada.

"""

return Person.from_dict(primero), Person.from_dict(segundo)

La función convert_pair() toma dos diccionarios que representan un par de programadores en la estructura JSON y utiliza el archivo . from_dict() constructor para convertirlos en  objetos Person. Para probar y explorar el código, se recomienda ejecutar el programa con el indicador -i para abrir el REPL interactivo de Python, permitiendo el acceso a todas las variables, clases y funciones definidas.

Ejecución del REPL interactivo de Python con el archivo "programmers.py" cargado

$ python -i programmers.py

 

Convertir el tercer programador de la lista "programadores" en un objeto "Persona"

Person.from_dict(programadores[2])

 

Salida: Objeto de persona con el nombre "Grace Hopper" y vida útil (1906, 1992)

Persona(name='Grace Hopper', life_span=(1906, 1992))

Convertiste con éxito la información de Grace Hopper en un objeto Person con su nombre completo y su vida útil. Para demostrar el efecto del rastreo, ahora intentaremos convertir al tío Barry.

# Acceso al primer elemento de la lista de 'programadores'

>>> programadores[0]

{'name': {'first': 'Uncle Barry'}}

 

# Intentando convertir el primer elemento de la lista 'programadores' en un objeto 'Persona'

>>> Person.from_dict(programadores[0])

 

# El rastreo se produce debido a un KeyError al intentar acceder al campo 'último' dentro del campo 'nombre'

Rastreo (última llamada más reciente):

Archivo "/home/realpython/programmers.py", línea 17, en from_dict

name=f"{info['name']['first']} {info['name']['last']}",

~~~~~~~~~~~~^^^^^^^^

 

La ausencia de la "última" clave dentro del campo "nombre" de los datos para el tío Barry hace que se genere un KeyError. Esto resalta la importancia de las anotaciones para aclarar la estructura de los datos.

 

De manera similar, la falta de información completa sobre la vida útil de Ada impide la creación de un objeto Persona para ella. Esto enfatiza la necesidad de una validación exhaustiva de los datos antes del procesamiento.

>>> programadores[1]

{

'nombre': {'primero': 'Ada', 'último': 'Lovelace'},

«nacimiento»: {'año': 1815},

'muerte': {'mes': 11, 'día': 27}

}

 

>>> Person.from_dict(programadores[1])

Rastreo (última llamada más reciente):

Archivo "/home/realpython/programmers.py", línea 18, en from_dict

life_span=(info["nacimiento"]["año"], info["muerte"]["año"]),

~~~~~~~~~~~~~^^^^^^^^

  • El código intenta crear un objeto Person  a partir de un diccionario que representa a un programador
  • El seguimiento indica un error en el proceso de creación, específicamente en la línea que define life_span
  • El KeyError: 'year' sugiere que el diccionario no contiene una clave de año para la información de muerte, lo que resulta en un error al intentar acceder a él.

Recibe otro KeyError, esta vez porque falta el atributo "año" para la muerte. El seguimiento resalta el atributo faltante dentro de la información de vida útil, lo que permite una resolución más rápida del problema.

¿Qué pasa con Guido? Solo tienes información sobre su nacimiento:

>>> programadores[4]

{

«nombre»: {'primero': 'Guido', 'último': 'Van Rossum'},

'nacimiento': {'año': 1956, 'mes': 1, 'día': 31},

'muerte': Ninguna

}

 

# Intento de convertir a un objeto Person

>>> Person.from_dict(programadores[4])

 

# Dando como resultado un TypeError, ya que el valor de "death" es None y no se puede subíndice

Rastreo (última llamada más reciente):

Archivo "/home/realpython/programmers.py", línea 18, en from_dict

life_span=(info["nacimiento"]["año"], info["muerte"]["año"]),

~~~~~~~~~~~~~^^^^^^^^

TypeError: el objeto 'NoneType' no es subscriptableTypeError:

 

 

En este escenario, se produce un TypeError. Tales errores de tipo que involucran 'NoneType' a menudo pueden ser difíciles de depurar debido a la falta de claridad sobre qué objeto no está definido. Sin embargo, la anotación de seguimiento proporciona información sobre el problema, lo que indica que info["death"] está establecido en None.Finalmente, examinaremos el resultado de las llamadas a funciones anidadas. Recuerde que la función convert_pair() invoca el método Person.from_dict() dos veces. Intentemos emparejar a Ada y Ole-Johan.

>>> convert_pair(programadores[3], programadores[1])

Rastreo (última llamada más reciente):

Archivo "/home/realpython/programmers.py", línea 24, en convert_pair

return Person.from_dict(primero), Person.from_dict(segundo)

# Error generado al convertir en primera persona

Archivo "/home/realpython/programmers.py", línea 18, en from_dict

life_span=(info["nacimiento"]["año"], info["muerte"]["año"]),

# Error generado al acceder al año de fallecimiento

KeyError: 'año'

 

Al intentar encapsular Ada, se produce el mismo KeyError que antes. El rastreo desde dentro de convert_pair() es notable en este escenario. En versiones anteriores de Python, habría sido difícil determinar si el error fue causado por el procesamiento de primero o segundo, ya que la función llama a .from_dict() dos veces. Sin embargo, en la última versión de Python, es inmediatamente evidente que el problema es con el segundo.

Estos rastreos mejorados en Python 3.11 hacen que la depuración sea más fácil que en versiones anteriores. Para obtener más ejemplos e información sobre la implementación de estos seguimientos, así como otras herramientas de depuración, puede consultar el tutorial de vista previa de Python 3.11 "Mensajes de error aún mejores". Además, para una perspectiva más técnica, puede consultar PEP 657.

Los rastreos anotados en Python 3.11 son un gran activo para los desarrolladores de Python, ya que aumentan su productividad. Además, esta versión de Python también es la más rápida hasta ahora.







Next Post Previous Post