martes, 3 de febrero de 2026

Python.


Listas. 
Manejo básico

Las listas son las colecciones nativas de datos más simples y flexibles con las que cuenta Python, lo que hace que sean usadas con mucha frecuencia.


Como dije [en su presentación], una lista es una colección ordenada y mutables de datos. Además los datos pueden ser de diferentes tipos (caracteres, cadenas, enteros, reales, booleanos) y pueden estar repetidos. Esto, junto con las operaciones permitidas sobre ella, la convierten en un recurso muy flexible.

En este cuaderno cómo trabajar con listas.


lunes, 2 de febrero de 2026

Python


Colecciones de datos nativas


Además de las variables, Python también permite trabajar con colecciones de datos. En el lenguaje-base están disponibles cuatro colecciones de datos, pero mediante bibliotecas complementarias podemos ampliar esta tipología básica. De momento, en esta entrada, nos limitaremos a presentar las colecciones nativas.

Empecemos por un breve resumen que nos ofrece Gemini a modo de síntesis.

ColecciónOrdenadaMutableDatos duplicados
Lista
TuplaNo
Conjunto (set)NoNo
DiccionarioClaves no, valores sí
En esta entrada, que hace de presentación, vamos a explicar brevemente cada una de ellas. En [este enlace] puedes acceder a la información que ofrece la página oficial de Python y en entradas posteriores trataremos cada una de ellas de forma más detallada y por separado.

Listas (list). Son colecciones ordenadas y mutables que permiten incluir datos duplicados. Son la mejor opción cuando necesitas trabajar con una secuencia de elementos ordenados y que se van a modificar frecuentemente.

A nivel de sintaxis se caracterizan por estar delimitadas por corchetes (mi_lista = [1, "hola", 3.14])

Tuplas (tuple). Son colecciones ordenadas e inmutables, lo que implica que no se pueden cambiar una vez creadas, lo que las hace más rápidas y seguras para datos que no deben variar.

A nivel sintáctico se presentan delimitadas por paréntesis (mi_tupla = (10, 20, 30))

Conjuntos (set). Son colecciones desordenadas y no indexadas. Su característica principal es que no permiten duplicados. 

Admite el cambio de datos, pero sólo en el sentido de que es posible añadir o quitar elementos siempre que estos, a su vez, sean inmutable, pero no elementos mutables. Esto implica que podemos añadir números, cadenas o tuplas (que son inmutables), pero no listas (que son mutables).

Son muy eficientes para operaciones matemáticas como uniones o intersecciones de conjuntos. Si convertimos una lista en un conjunto se eliminarán los elementos repetidos que podía contener la lista, lo que permite plantear procedimientos interesantes; uno de ellos es la verificación de la pertenencia de un dato a un conjunto.

Su sintaxis (mi_set = {1, 2, 3, 3}) es el uso de las llaves como delimitador.

Diccionarios (dict). Son colecciones de pares clave-valor, extremadamente rápidos para buscar información conociendo la clave. Su uso es interesante para representar objetos (POO) y para trabajar con bases de datos en memoria o en mapeos.

Se identifican sintácticamente por estar delimitados por llaves (mi_dict = {"nombre": "Ana", "edad": 25}) junto con la estructura llave:valor.

martes, 23 de diciembre de 2025

Evaluación

Automatización de la evaluación


Análisis de la puntuación total mediante OOo Basic



Normalmente lo primero que se analiza de los resultados de la aplicación de un test es el sumatorio de las puntuaciones obtenidas, bien para convertirlas a algún tipo de escala en función de unos estadísticos, bien para compararla con un criterio de nivel de ejecución. 

En ambos casos podemos encontrarnos con datos que tienen un único y posible significado o diferente en función de determinado referente, como puede ser la edad del sujeto o su nivel o curso.

Cuando el significado es único el procedimiento que sigue no se diferencia mucho del expuesto en [esta entrada], aunque empleemos código OOo Basic en lugar de funciones Calc. Pero cuando el significado es diferente en función de, por ejemplo, la edad, previamente podemos que realizar ciertos procesos para automatizar correctamente el análisis y no tener que plantear procedimientos específicos para cada edad o contexto de referencia.

Aunque hay muchos, el test PLON-R. Fonología es un ejemplo de lo que acabo de exponer: una misma puntuación total o directa (PD) tiene significados diferentes en función de la edad. Por ejemplo, obtener 21 ptos es lo esperado para 3 años, ya que indica que el niño pronuncia correctamente todos los fonemas y grupos fonémicos propios de su edad, pero es indicador de déficit para el resto de las edades. Lo mismo sucede con la PD 44, aunque en este caso es indicador de error en la aplicación del test para niños de 3 años (o de alto nivel de desarrollo fonológico), se ajusta a lo esperado para 4 años y es indicador de déficit para edades superiores.

Es por ello que antes de realizar cualquier valoración de la PD, antes deberemos ponerla en relación con la edad (en este caso). La forma de realizar esta operación de forma automatizada, sin que sea necesario explicitar conocimiento de los datos propios del grupo de referencia ni desarrollar procedimientos específicos para cada edad, es trabajar con matrices y con bucles.

Este procedimiento ya [ha sido empleado] en el tratamiento del input con otros objetivos, pero es suficientemente interesante como para que de nuevo le dediquemos nuestra atención.

Partimos del conocimiento de dos datos del sujeto: su edad y la PD que obtuvo, pero también de los posibles valores que pueden tener ambos datos. Los primeros los almacenamos en sendas variables (edad y pd) y los segundos en dos matrices; una para las edades...

Dim edades() As Integer
edades = Array(3,4,5,6)

... y otra para las PD esperadas para cada edad.

Dim ptos_max() AS Integer
ptos_max = Array(21,44,56,61)

Como puedes ver ambas colecciones de datos guardan relación (se emparejan) en función de la posición que ocupan en sus respectivas matrices: edades(0) guarda el valor (años) del primer grupo etario (3) y ptos_max(0) el valor de la PD esperada del primer grupo etario (21).

3 años -> 21 ptos en total

Precisamente en la equivalencia de posiciones de edades y valores PD está la base de automatización; gracias a ella nos podemos olvidar de los valores numéricos y limitarnos a recorrer las matrices con un bucle y a realizar comparaciones condicionales.
  • Primero. Recorremos la matriz mediante For 
For i = 0 To UBound(edades()))
  • Segundo. Localizamos el valor posicional de la edad real del sujeto y la utilizamos como primera condición
For i = 0 To UBound(edades())
If edades(i) = edad Then
    -> [Segunda condición]
End If
Next 
  • Tercero. Cuando el recorrido del bucle hace True la primera condición, lanzamos el segundo análisis condicional sobre el que realizamos la valoración de la pd del sujeto.
If pd = ptos_max(i) Then
Valoracion = "Acierto total"
Else
Valoracion = "Resultado insuficiente"
End If

Esta es la forma más simple en la que se realiza la valoración de la PD, pero posiblemente la menos común. De todas formas, es fundamental, ya que, por muy complejas que sean las demás, todas parten de la relación que establecemos mediante la estructura que hemos explicado.

Evaluación

Automatización de la evaluación

Input incremental (II)




Dado que en la [entrada anterior] establecimos previamente los diferentes soportes de interfaz para la fase input, en esta daremos un paso más y crearemos esa interfaz a partir de los datos de una matriz y en función de la edad. En este caso es así dadas las características de la prueba de referencia (PLON-R. Fonología).

No se trata de un procedimiento totalmente automatizado, ya que la hoja sobre la que crearemos la interfaz y parte de los elementos que contiene han tenido que ser creada previamente, pero lo que ahora nos interesa es la parte nuclear de su contenido: el listado de palabras que deberá producir el alumno y que deberemos evaluar nosotros.

Este modo de resolver la cuestión nos ahorra crear tantas hojas/interfaces como grupos input existan en la prueba. Así en PLON-R. Fonología resolvemos con una lo que según el procedimiento anterior precisaba cuatro. Se eliminan también unos cuantos script asociados al manejo de esas hojas.

Sub CrearLista

Dim oHoja As Object, oCelda As Object
Dim listado() As String

Dim annos As String
Dim edad As Integer

annos = al_edad()
edad = CInt(annos)

If edad > 6 Then
edad = 6
End If

listado() = copiaPal(edad)

'Acceso a la página

oHoja = ThisComponent.getSheets().getByName("ListaPal")

oCelda = oHoja.getCellRangeByName("B2")
oCelda.setString("Palabras")
oCelda = oHoja.getCellRangeByName("C2")
oCelda.setString("Puntos")

For i = 0 To UBound(listado())
oCelda = oHoja.getCellRangeByName("B" & i+3)
oCelda.setString(listado(i))
Next

End Sub

Pasemos ahora a analizar cómo se desarrolla esta propuesta. El primer paso consiste en acceder a la edad del sujeto, ya que ésta es la que determinará el desarrollo del resto. Para ello, desde nuestro script principal, haremos uso de la función, creada en versiones anteriores, que nos permitía acceder a ese datos (annos = al_edad()). 

Function al_edad () As string

Dim oHoja As Object, oCelda As Object
Dim i As Integer
Dim edad As String

'Acceso a Resultados para capturar la edad
oHoja = ThisComponent.getSheets().getByName("Resultados")
oCelda = oHoja.getCellRangeByName("B4")
edad = oCelda.getString

al_edad = edad

End Function

Una vez que disponemos de ese dato (string) lo convertimos a integer (edad = CInt(annos)) para operar con él (If edad > 6 Then -> edad = 6 -> End If), evitando posibles errores en el manejo de los datos de edad cuando ésta supera los 6 años.

El paso siguiente consiste en acceder a la función que nos da acceso al contenido con el que trabajar (listado() = copiaPal(edad)): el listado de palabras que corresponde por edad y que deberemos recuperar de la hoja Matrices.

Function CopiaPal(al_edad As Integer)

'para acceso a objetos
Dim oHoja As Object, oCelda As Object
Dim listaPal () As String

'Para acceso a datos
Dim i As Integer
Dim max As Integer
Dim edades() As Integer
Dim ptos_max() AS Integer

edades = Array(3,4,5,6)
ptos_max = Array(21,44,56,61)

'Calculo y establecimiento del límite superior del listado

For i = 0 To UBound(edades())
If edades(i) = al_edad Then
max = ptos_max(i)
End If
Next 

ReDim listaPal(max-1)

'Acceso a la hoja que contiene la base de datos

oHoja = ThisComponent.getSheets().getByName("Matrices")

For i = 0 To UBound(listaPal())
oCelda = oHoja.getCellRangeByName("I" & i+1)
listaPal(i) = oCelda.getString()
Next

CopiaPal = listaPal()

End Function

Esta función accede al contenido de la hoja Matrices y accede al valor numérico de la extensión del listado que debe crear haciendo uso del parámetro al_edad que le hemos pasado desde el script principal, mediante una analogía entre los valores de posición de la matriz edades y los de la matroz ptos_max.

For i = 0 To UBound(edades())
If edades(i) = al_edad Then
max = ptos_max(i)
End If
Next 

Con ese dato de longitud o límite superior redimensionamos la matriz que contendrá el listado de palabras (ReDim listaPal(max-1)). Mediante un segundo bucle recorremos la columna I y accedemos a las palabras que incluimos como elementos de la matriz (listaPal(i) = oCelda.getString()) que la función devolverá al script principal (CopiaPal = listaPal()).

De regreso a éste, sólo nos queda posicionarnos en la hoja sobre la que escribir los títulos de las columnas...

oCelda = oHoja.getCellRangeByName("B2")
oCelda.setString("Palabras")

... y el listado y proceder a ello mediante el procedimiento ya conocido de asignar contenido a las celdas.

For i = 0 To UBound(listado())
oCelda = oHoja.getCellRangeByName("B" & i+3)
oCelda.setString(listado(i))
Next

Si deseáramos completar el procedimiento y dejar listo los materiales para un uso posterior deberíamos implementar código que capture el resultado de la aplicación del test (puntuación de cada ítem) para trasladarlos a la hoja Resultados, eliminando antes el contenido de la lista de palabras y de la puntuación.

A parte de este posible desarrollo del script, también nos podemos plantear otros que implican establecer un condicionamiento múltiple. Un ejemplo sobre PLON-R. Fonología podría ser seleccionar únicamente los fonemas y no los grupos fonémicos, o sólo los fonemas oclusivos, o sólo los fonemas sonoros... Los ejemplos son múltiples, tantos como variables diferenciadoras hayamos establecido. Además esas subcategorizaciones podemos establecerlas secuencialmente o mediante condicionales anidados. En cualquier caso, lo interesante es que podemos hacer uso del procedimiento básico que hemos explicado en esta entrada para automatizar la selección del contenido sobre el que trabajar en función de los criterios que nos interese aplicar en cada caso.