Volver al catálogo
Season 34 7 Episodios 28 min 2026

NumPy

v2.4 — Edición 2026. Un curso en audio para introducir NumPy, explicando su alto rendimiento, los arrays multidimensionales y su papel fundamental en el ecosistema de Python. (v2.4, Edición 2026)

Ciencia de datos Python Core
NumPy
Reproduciendo ahora
Click play to start
0:00
0:00
1
La identidad central: ndarray
Este episodio cubre el objeto ndarray, los tipos de datos homogéneos y la asignación de memoria fija. Aprenderás por qué las listas estándar de Python son ineficientes para matemáticas a gran escala y cómo NumPy lo soluciona recurriendo a código C compilado.
3m 58s
2
Invocando arrays: Creación y forma
Este episodio explora cómo crear correctamente arrays multidimensionales utilizando funciones intrínsecas. Aprenderás a usar herramientas como zeros, arange y linspace para generar conjuntos de datos al instante.
4m 13s
3
Bajo el capó: Memoria, strides y vistas
Este episodio profundiza en la arquitectura interna de NumPy, centrándose en el búfer de datos y los strides. Aprenderás por qué operaciones como el slicing y la transposición son prácticamente instantáneas, ya que devuelven vistas de memoria, no copias.
4m 13s
4
Funciones universales: Matemáticas sin bucles
Este episodio cubre las funciones universales (ufuncs) y cómo vectorizan las operaciones. Aprenderás a eliminar por completo los bucles for de Python aplicando matemáticas elemento a elemento y reducciones basadas en ejes.
3m 54s
5
Broadcasting: La magia de las formas discordantes
Este episodio explica las reglas exactas del Broadcasting. Aprenderás cómo NumPy estira conceptualmente arrays de formas diferentes para que puedan procesarse juntos sin desperdiciar memoria.
4m 18s
6
Filtrado de precisión: Enmascaramiento booleano
Este episodio se centra en el enmascaramiento booleano avanzado para filtrar conjuntos de datos complejos. Aprenderás a extraer puntos de datos muy específicos de arrays masivos utilizando lógica condicional simple.
3m 45s
7
El traductor universal: Interoperabilidad
Este episodio revela por qué NumPy sigue siendo la columna vertebral de la ciencia de datos en Python. Aprenderás cómo DLPack y la interfaz de array permiten compartir memoria zero-copy entre herramientas como Pandas y PyTorch.
4m 14s

Episodios

1

La identidad central: ndarray

3m 58s

Este episodio cubre el objeto ndarray, los tipos de datos homogéneos y la asignación de memoria fija. Aprenderás por qué las listas estándar de Python son ineficientes para matemáticas a gran escala y cómo NumPy lo soluciona recurriendo a código C compilado.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. NumPy, episodio 1 de 7. La list estándar de Python es muy flexible, pero en cuanto intentas hacer operaciones matemáticas con un millón de elementos, te chocas contra un muro de rendimiento. Acabas pagando un peaje de pointers enorme solo para multiplicar números. La solución a este cuello de botella es el motor principal de la computación científica en Python: el ndarray. Para entender por qué existe el ndarray, tienes que mirar qué hacen las lists estándar por debajo. Una list de Python no almacena números en crudo. Almacena pointers. Cada pointer dirige al sistema a una ubicación dispersa en la memoria donde vive un objeto de Python completo. Si escribes un loop estándar para multiplicar dos secuencias de un millón de números, el intérprete de Python trabaja muchísimo. Para cada elemento, recupera el pointer, localiza el objeto, comprueba su tipo de dato para confirmar que es realmente un número, hace el cálculo matemático y almacena el nuevo objeto. Hacer esto un millón de veces introduce un overhead enorme. Este ciclo de perseguir pointers y comprobar tipos es la razón por la que los loops estándar son simplemente demasiado lentos para operaciones matemáticas grandes. El ndarray, que significa array N-dimensional, sacrifica esta flexibilidad a cambio de velocidad pura. La parte N-dimensional significa que este objeto puede representar una secuencia plana de números, una cuadrícula bidimensional o una matriz matemática multidimensional compleja. Independientemente de cuántas dimensiones definas, por debajo, opera con dos reglas estrictas. Primero, requiere tipos de datos homogéneos. Cada elemento de un ndarray debe ser exactamente del mismo tipo, como un float de sesenta y cuatro bits. Segundo, utiliza un tamaño de memoria fijo. Cuando creas un ndarray, NumPy reserva un único bloque de memoria continuo. No hay pointers. Los números en crudo están empaquetados unos junto a otros en la memoria del sistema. Aquí está la clave. Como NumPy conoce el tipo de dato exacto y el layout de memoria exacto, puede saltarse por completo el lento intérprete de Python. Cuando multiplicas dos ndarrays que contienen un millón de números, no escribes un loop. Simplemente escribes el array A multiplicado por el array B. Este proceso se llama vectorización. NumPy coge tu comando y le pasa el cálculo real a código C precompilado. El código C vuela por ese bloque continuo de memoria a velocidades de hardware. Se salta la comprobación de tipos y las búsquedas de pointers para los elementos individuales porque la memoria es perfectamente uniforme. El trade-off de este enorme aumento de velocidad es la rigidez estructural. Como la memoria es un bloque continuo, no puedes simplemente hacer un append de un nuevo número a un ndarray como lo haces con una list de Python. Si necesitas un array más grande, por lo general NumPy tiene que reservar un bloque de memoria totalmente nuevo y copiar los datos antiguos. Construyes el contenedor con el tamaño exacto que necesitas, y luego ejecutas tus operaciones en todo el bloque a la vez. La list estándar de Python es una colección de objetos aislados esparcidos por la memoria. El ndarray de NumPy es un bloque denso y uniforme de datos en crudo, diseñado para ser procesado al instante por código C optimizado. Si disfrutas de estos episodios y quieres apoyar el programa, puedes buscar DevStoriesEU en Patreon. Eso es todo por este episodio. ¡Gracias por escuchar, y sigue programando!
2

Invocando arrays: Creación y forma

4m 13s

Este episodio explora cómo crear correctamente arrays multidimensionales utilizando funciones intrínsecas. Aprenderás a usar herramientas como zeros, arange y linspace para generar conjuntos de datos al instante.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. NumPy, episodio 2 de 7. En ciencia de datos, rara vez escribes los datos a mano. En su lugar, necesitas generar enormes cuadrículas vacías y rangos numéricos con un solo comando. Hablemos de las funciones intrínsecas que te permiten crear arrays desde cero y controlar su estructura. Primero, una rápida corrección sobre la creación manual. Cuando conviertes una lista estándar de Python en un array usando la función array básica, un error común es pasar varios argumentos por separado para crear múltiples dimensiones. La función espera una sola secuencia. Para crear un array bidimensional, pasas una lista que contiene otras listas, no dos listas separadas. Cada array que creas contiene metadatos estructurales. Aquí importan sobre todo dos propiedades. La primera es ndim, que te indica el número de ejes, o dimensiones, que tiene el array. Una secuencia plana tiene un ndim de uno, mientras que una cuadrícula plana tiene un ndim de dos. La segunda propiedad es shape. Shape es un tuple de enteros que indica el tamaño exacto del array en cada dimensión. Si tienes una matriz con dos filas y tres columnas, su shape es de dos por tres. La longitud del tuple shape siempre será igual al valor de ndim. Crear arrays a partir de listas existentes está bien para pruebas pequeñas, pero el trabajo real requiere generar arrays programáticamente. Si necesitas un placeholder para rellenar con datos más tarde, usas las funciones zeros o ones. Simplemente pasas un tuple shape a estas funciones, y te devuelven un array con esa estructura exacta, relleno completamente de ceros o unos. Por defecto, estas funciones crean números float, pero puedes sobrescribir esto especificando un data type diferente. Cuando necesitas una secuencia de números, NumPy ofrece dos herramientas principales. La primera es arange, que funciona de forma muy parecida al range estándar de Python. Le das un valor de inicio, un valor de parada y un tamaño de step. Genera un array de números espaciados por ese step. Aunque arange es genial para enteros, usarlo con steps float puede causar resultados impredecibles debido a cómo los ordenadores manejan la precisión decimal. El número de elementos que obtienes de vuelta puede variar ligeramente dependiendo de errores microscópicos de redondeo. Eso nos lleva a linspace, que resuelve el problema de precisión del floating-point. En lugar de definir el tamaño del step, defines el número exacto de elementos que quieres. Le das a linspace un valor de inicio, un valor de parada y el número total de puntos. NumPy calcula el espaciado exacto por ti. Considera un escenario donde estás evaluando una función matemática en un intervalo específico. Quieres calcular la función a través de una cuadrícula suave de coordenadas entre cero y uno. Usando linspace, puedes generar exactamente cien coordenadas espaciadas uniformemente a lo largo de ese intervalo. Obtienes un array unidimensional perfectamente distribuido, garantizando que tanto el límite de inicio como el de fin estén incluidos. Aquí es donde se pone interesante. La distinción entre estos dos generadores de secuencias dicta tu workflow. Usa arange cuando el tamaño exacto del step importe, como al contar enteros de dos en dos, pero usa siempre linspace cuando trabajes con floats e intervalos para que puedas garantizar exactamente cuántos data points obtienes y alcanzar tus límites con precisión. Gracias por escuchar — nos vemos en la próxima.
3

Bajo el capó: Memoria, strides y vistas

4m 13s

Este episodio profundiza en la arquitectura interna de NumPy, centrándose en el búfer de datos y los strides. Aprenderás por qué operaciones como el slicing y la transposición son prácticamente instantáneas, ya que devuelven vistas de memoria, no copias.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. NumPy, episodio 3 de 7. Tienes una matriz de mil millones de píxeles y necesitas invertir sus filas y columnas. Si lo haces en Python estándar, tu máquina se quedará bloqueada mientras copia gigabytes de datos. En NumPy, esta operación ocurre al instante. En realidad, reordenar esos píxeles no mueve ni un solo byte de memoria. Esto ocurre por cómo NumPy gestiona la memoria, los strides y las views por debajo. Para entender por qué NumPy es tan rápido, tienes que fijarte en la estructura interna de un array. Un array de NumPy no es un objeto único y monolítico. Está estrictamente separado en dos partes. La primera parte es el data buffer. Se trata de un bloque contiguo y plano de memoria raw. Es simplemente una línea unidimensional de bytes alojada en la RAM. El raw buffer no sabe absolutamente nada de filas, columnas o dimensiones. La segunda parte son los metadatos. Se trata de una pequeña cabecera, implementada internamente como una estructura de C, que le dice a NumPy cómo interpretar esa línea de bytes raw. Los metadatos contienen un pointer al inicio del data buffer, el tipo de dato, el shape del array y los strides. Los strides son el mecanismo que transforma una línea plana de memoria en una cuadrícula multidimensional. Un stride es simplemente el número de bytes que el ordenador debe avanzar en memoria para encontrar el siguiente elemento a lo largo de un eje específico. Supón que tienes un array bidimensional de enteros de 64 bits. Cada entero ocupa ocho bytes. Para moverte una columna a la derecha, el stride podría ser de ocho bytes. Pero para bajar a la siguiente fila, el stride podría ser de ochenta bytes, porque tiene que saltarse una fila entera de datos en el raw buffer para encontrar el inicio de la siguiente. Muchos desarrolladores asumen que cuando haces un slice de un array, el sistema reserva nueva memoria y copia los datos seleccionados. Eso es incorrecto. Cuando pides un slice, NumPy deja el raw data buffer completamente intacto. En su lugar, crea una nueva cabecera de metadatos. Esta nueva cabecera apunta exactamente al mismo bloque de memoria, pero cambia el pointer de inicio y modifica los strides para saltarse los elementos que has excluido. A esto se le llama una view. Aquí está la clave. Como los datos raw y los metadatos se mantienen separados, las operaciones que cambian el shape o el orden del array son casi completamente gratis. Piensa de nuevo en transponer esa enorme matriz de mil millones de píxeles. NumPy no coge los datos y los reorganiza físicamente. Simplemente intercambia los valores de los strides en la nueva cabecera de metadatos. El número de bytes que antes saltabas para encontrar la siguiente fila se convierte en el número que saltas para encontrar la siguiente columna. Se devuelve a tu código una estructura de array completamente diferente, pero es solo una view mirando exactamente a la misma memoria física. Esta separación es la base de la eficiencia de memoria de NumPy. Puedes trocear un dataset enorme en docenas de slices superpuestos, pasarlos a diferentes funciones, y consumir cero memoria extra para los datos en sí. Solo estás generando pequeñas cabeceras de metadatos. Sin embargo, esto significa que compartes state. Modificar un valor en un slice alterará el array original, porque solo hay un data buffer real por debajo de todos ellos. La separación de los bytes raw de las reglas que los gobiernan significa que tus transformaciones de datos más pesadas a menudo son solo ligeros intercambios de metadatos. Eso es todo por este episodio. ¡Gracias por escuchar, y sigue programando!
4

Funciones universales: Matemáticas sin bucles

3m 54s

Este episodio cubre las funciones universales (ufuncs) y cómo vectorizan las operaciones. Aprenderás a eliminar por completo los bucles for de Python aplicando matemáticas elemento a elemento y reducciones basadas en ejes.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. NumPy, episodio 4 de 7. Si alguna vez te encuentras escribiendo un bucle for para multiplicar números en un array, para. Hacer eso significa que estás pagando el overhead del intérprete de Python por cada elemento, y tu código se está ejecutando cien veces más lento de lo necesario. La solución es usar funciones universales para realizar operaciones matemáticas sin bucles. Un error común es intentar pasar un array completo a una función del módulo math estándar de Python. Si pasas un millón de lecturas de sensores a math punto sine, Python lanza un error. El módulo math estándar solo entiende valores escalares individuales. Para procesar un array, normalmente tendrías que escribir un bucle. Pero Python es un lenguaje dinámico. Dentro de un bucle, el intérprete evalúa el tipo de dato en cada iteración antes de calcular el resultado. Cuando procesas datasets masivos, esas pequeñas pausas de type-checking se acumulan y crean un bottleneck de rendimiento importante. Una función universal, o ufunc, resuelve esto operando sobre los arrays elemento por elemento automáticamente. Cuando llamas a una ufunc, NumPy delega la ejecución del bucle a código C compilado. Como los arrays de NumPy tienen un único tipo de dato uniforme, el código C no necesita pausarse y comprobar los tipos. Itera sobre bloques contiguos de memoria y calcula el resultado tan rápido como tu procesador lo permita. Veamos un escenario concreto. Tienes un array que contiene miles de lecturas de sensores ambientales, y necesitas aplicar una transformación matemática a todas a la vez. En lugar de escribir un bucle, simplemente pasas todo el array a una función universal como numpy punto exp o numpy punto sin. La ufunc toma tu array de entrada, ejecuta el bucle rápido a nivel de C por cada elemento, y devuelve un array completamente nuevo lleno de las lecturas transformadas. Esta es la parte que importa. Las ufuncs hacen más que solo transformaciones elemento por elemento. Contienen métodos built-in para colapsar datos, saltándose Python por completo para las agregaciones. El más común es el método reduce. Supón que aplicaste tu transformación matemática, y ahora necesitas la suma total de todo el array. Llamas al método reduce directamente sobre la ufunc de suma. Escribes numpy punto add punto reduce, y le pasas tu array. El método reduce aplica la operación de suma subyacente a los dos primeros elementos. Toma esa suma, la añade al tercer elemento, y continúa este patrón hasta que todo el array colapsa en un único valor escalar. Si tus datos tienen múltiples dimensiones, puedes controlar cómo ocurre este colapso. Si las lecturas de tus sensores forman un grid bidimensional, donde las filas son diferentes sensores y las columnas son timestamps individuales, reducir todo el grid a un solo número destruye esa estructura. Al proporcionar un argumento axis, controlas la dirección de la operación. Si le dices al método reduce que opere a lo largo del axis cero, colapsa las filas, dejándote con un array que contiene la suma de todos los sensores en cada timestamp individual. Cada vez que dejas que una función universal maneje la iteración de forma nativa, estás cambiando los bucles lentos de Python por una ejecución en C optimizada por hardware. Gracias por escuchar. ¡Hasta la próxima!
5

Broadcasting: La magia de las formas discordantes

4m 18s

Este episodio explica las reglas exactas del Broadcasting. Aprenderás cómo NumPy estira conceptualmente arrays de formas diferentes para que puedan procesarse juntos sin desperdiciar memoria.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. NumPy, episodio 5 de 7. ¿Qué sucede cuando intentas multiplicar una matriz tridimensional de un millón de píxeles por un pequeño array de tres números? En muchos lenguajes estrictos, se produce un error de shape mismatch. En NumPy, simplemente funciona. Este comportamiento se denomina broadcasting. El broadcasting describe cómo NumPy trata los arrays con diferentes shapes durante las operaciones aritméticas. Toma el array más pequeño y lo expande conceptualmente sobre el más grande para que sus shapes se alineen perfectamente. A menudo, los oyentes creen erróneamente que esta expansión copia físicamente los datos para construir un nuevo array coincidente en memoria. No es así. NumPy gestiona esta alineación implícitamente a nivel de C. Itera sobre los mismos elementos varias veces con cero memory overhead, lo que hace que el broadcasting sea increíblemente rápido y altamente eficiente. Para usarlo, debes comprender cómo NumPy decide si dos arrays son compatibles. No considera el número total de elementos, sino las tuplas de shape. NumPy alinea los shapes de los dos arrays y los compara comenzando por las trailing dimensions (las del extremo derecho) y avanzando hacia la izquierda. Dos dimensiones son compatibles si cumplen una de dos condiciones estrictas: deben ser exactamente iguales o una de ellas debe ser el número uno. Si en algún punto de la comparación no se cumple ninguna de las dos condiciones, NumPy lanza un ValueError y la operación falla. Veamos un ejemplo concreto. Estás trabajando con una imagen RGB. La cargas en un array de NumPy con un shape de 256 por 256 por 3. El 3 representa los canales de color rojo, verde y azul al final del shape. Ahora, necesitas corregir el color de esta imagen escalando cada canal de forma diferente. Defines un array unidimensional con tres pesos de corrección de color. El shape de este array es simplemente 3. Al multiplicar el array gigante de la imagen por el pequeño array de pesos, NumPy aplica la regla de derecha a izquierda. Coloca el shape de la imagen, de 256 por 256 por 3, encima del shape de los pesos, que es simplemente 3. Comenzando por el extremo derecho, se comparan las trailing dimensions. Ambas son 3. Como son iguales, son compatibles. Luego, NumPy se mueve a la izquierda. El array de la imagen tiene una dimensión de 256, pero el array de pesos se ha quedado sin dimensiones por completo. Aquí es donde entra en juego la segunda parte de la regla. Cuando un array tiene menos dimensiones que el otro, NumPy hace un prepend implícito de unos a su shape hasta que coinciden en longitud. El shape del array de pesos se trata como 1 por 1 por 3. Ahora la comparación continúa. La imagen tiene una dimensión de 256, y el array de pesos ahora tiene una dimensión de 1. Como uno de ellos es 1, son compatibles. El array de pesos se expande conceptualmente a lo largo de las 256 filas. Esto se repite para la siguiente dimensión. Los shapes se alinean y NumPy aplica tus tres pesos de color a los sesenta y cinco mil píxeles sin problemas. Esta es la parte importante. La regla solo funciona de derecha a izquierda. Si tienes un array bidimensional con un shape de 5 por 4 e intentas sumarle un array de shape 5, podrías pensar que se extenderá a lo largo de las columnas. No es así. Empezando por la derecha, NumPy compara 4 y 5. No son iguales, y ninguno de los dos es un uno. La operación falla inmediatamente. Para que funcione, tendrías que hacer un reshape del segundo array a 5 por 1 primero. El broadcasting te permite escribir código limpio y loop-free que se ejecuta a velocidades de código compilado. La regla de oro es siempre las trailing dimensions primero: deben coincidir exactamente, o una de ellas debe ser un uno. Gracias por escuchar. ¡Hasta la próxima!
6

Filtrado de precisión: Enmascaramiento booleano

3m 45s

Este episodio se centra en el enmascaramiento booleano avanzado para filtrar conjuntos de datos complejos. Aprenderás a extraer puntos de datos muy específicos de arrays masivos utilizando lógica condicional simple.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. NumPy, episodio 6 de 7. Extraer todos los números negativos de un array de mil millones de elementos no es un problema de búsqueda. No debería requerir un loop, y desde luego, no debería ralentizar tu aplicación. Aquí es donde usamos el filtrado de precisión: el boolean masking. El slicing básico extrae fragmentos de datos ordenados y predecibles. Pero los datos del mundo real son un caos. Rara vez quieres solo los diez primeros elementos. Quieres elementos específicos basados en una condición lógica, y esos elementos pueden estar dispersos aleatoriamente por todo tu dataset. En NumPy, extraer datos de esta manera se llama advanced indexing, y el boolean masking es una de sus formas más potentes. Imagina un array enorme de lecturas de temperatura. Necesitas aislar solo los valores que caen por debajo de cero. En lugar de escribir un loop para comprobar cada lectura una por una, usas una mask. Una mask es un array de valores booleanos, es decir, True o False. Lo fundamental es que este array booleano tiene exactamente el mismo shape que tu array de datos original. Lo creas aplicando una condición de menor que cero directamente al array. NumPy evalúa al instante todos y cada uno de los elementos. Si una temperatura es menor que cero, la mask registra un True en esa posición exacta. Si la temperatura es cero o superior, registra un False. Una vez que tienes esta mask, se la aplicas al array original pasándola exactamente donde normalmente pondrías un índice. NumPy lee la mask, selecciona cada elemento donde la mask es True, y descarta el resto. La operación genera un array unidimensional totalmente nuevo que contiene únicamente tus temperaturas bajo cero. Ocurre en un solo paso, ejecutado por debajo mediante código C altamente optimizado. Presta atención a esta siguiente distinción, porque confunde a muchos developers. Necesitas saber exactamente qué te devuelve NumPy cuando filtras datos. El slicing básico devuelve una view. Si haces un slice de los diez primeros elementos de un array y los modificas, el array original cambia. El boolean masking se comporta de forma completamente distinta. Como el boolean masking es una forma de advanced indexing, siempre devuelve una copy de los datos, nunca una view. La razón es la arquitectura de memoria. Cuando haces slicing, NumPy simplemente cambia los pointers a un bloque de memoria continuo y ya existente. Pero cuando aplicas una boolean mask, los elementos que seleccionas son completamente arbitrarios. Ya no están ordenados uno junto al otro en la memoria. NumPy tiene que agruparlos y asignar nuevo espacio para almacenar el resultado. Esto significa que si modificas tu array recién filtrado de temperaturas bajo cero, tu dataset original permanece completamente intacto. También puedes encadenar estas condiciones. Si necesitas temperaturas que estén por debajo de cero pero estrictamente por encima de menos diez grados, combinas las dos condiciones lógicas. NumPy evalúa la lógica combinada elemento por elemento y construye una única mask precisa. Cuando aplicas una boolean mask, estás intercambiando la eficiencia de memoria de una view por una precisión de filtrado absoluta, dándote una copy prístina e independiente de exactamente los datos que pediste. Eso es todo por este episodio. Gracias por escuchar, ¡y sigue construyendo!
7

El traductor universal: Interoperabilidad

4m 14s

Este episodio revela por qué NumPy sigue siendo la columna vertebral de la ciencia de datos en Python. Aprenderás cómo DLPack y la interfaz de array permiten compartir memoria zero-copy entre herramientas como Pandas y PyTorch.

Descargar
Hola, soy Alex de DEV STORIES DOT EU. NumPy, episodio 7 de 7. Con los modernos frameworks de GPU encargándose del trabajo pesado en machine learning, podrías pensar que NumPy se está quedando obsoleto. Incluso podrías suponer que convertir un tensor de CPU de PyTorch a un array de NumPy requiere una copia de memoria lenta, ralentizando tu pipeline. Ninguna de las dos cosas es cierta. La realidad es que NumPy actúa como el traductor universal: la interoperabilidad que mantiene unido todo el ecosistema de datos de Python. Piensa en un pipeline estándar de machine learning. Usas Pandas para cargar y limpiar un dataset tabular enorme. Extraes esos valores a NumPy para aplicar un filtro matemático especializado. Finalmente, pasas esos datos filtrados a PyTorch para entrenar una red neuronal. Si cada una de estas librerías aislara sus datos, pasar de un paso a otro significaría duplicar todo el dataset en memoria una y otra vez. Agotarías tu RAM y desperdiciarías tiempo de procesamiento simplemente moviendo bytes de un lado a otro. En cambio, gracias a la magia de la interoperabilidad, los datos nunca se mueven realmente. Pandas, NumPy y PyTorch simplemente comparten exactamente el mismo puntero de memoria subyacente. Cuando PyTorch lee los datos, está mirando exactamente las mismas direcciones de memoria física que Pandas asignó originalmente. Esta compartición zero copy es posible gracias a los protocolos de memoria estándar. El fundamental es la array interface. Si un objeto de Python expone esta interfaz, básicamente entrega un pequeño diccionario de metadatos. Estos metadatos le dicen a NumPy exactamente dónde empieza el raw data en memoria, qué shape tiene y qué data type contiene. Cuando llamas a una función de NumPy sobre un objeto compatible, NumPy lee esas instrucciones y envuelve el bloque de memoria existente con su propia estructura de array. No crea un array nuevo; simplemente crea una nueva view de los datos antiguos. Aquí está la clave. La array interface original se diseñó principalmente para la memoria estándar del sistema. A medida que la data science se movió hacia los aceleradores de hardware, el ecosistema necesitó una forma de compartir datos que vivían en GPUs o chips personalizados sin tener que enrutarlos de vuelta a través de la CPU. Esto llevó a la adopción de DLPack. DLPack es un estándar abierto y moderno para compartir arrays multidimensionales entre diferentes frameworks. Define una estructura estable que cualquier librería puede producir y consumir. Si tienes un tensor en un framework como PyTorch o JAX, puedes exportarlo usando el protocolo DLPack. NumPy puede entonces importarlo de forma transparente usando su función dedicada from dlpack. Aunque NumPy opera principalmente en la CPU, su soporte para DLPack significa que puede actuar como el hub de enrutamiento central. Puedes pasar un objeto DLPack desde un framework de deep learning a NumPy, o de NumPy de vuelta a un framework, todo sin una costosa duplicación de datos. Hace mucho tiempo que NumPy dejó de ser solo una librería matemática. Es el estándar de memoria invisible que evita que el ecosistema de datos de Python se fragmente en islas aisladas e incompatibles. Te animo a explorar la documentación oficial, probar estas conversiones zero copy de forma práctica en tu propia terminal, o visitar devstories dot eu para sugerir temas para nuestras futuras series. Eso es todo por este episodio. ¡Gracias por escuchar, y a seguir creando!