Mostrando entradas con la etiqueta Variables. Mostrar todas las entradas
Mostrando entradas con la etiqueta Variables. Mostrar todas las entradas

miércoles, 16 de abril de 2025

Datos. Estadística

Tipos de variables


Una variable es un fenómeno observable que puede adoptar diferentes valores excluyentes entre sí. Las variables pueden ser medibles o no; en el segundo caso hablamos de atributos, que. a su vez, pueden ser ordenables o no. A nivel eminentemente práctico, diferenciar entre los distintos tipos de variables incide en las operaciones estadísticas que es posible realizar con los datos; esto es, afecta a las escalas de media a utilizar. 



Según las escalas de medida, las variables se diferencian entre cualitativas (nominales y ordinales) y cuantitativas (de intervalo y de razón).

La escala nominal permite diferenciar entre características, pero no realizar operaciones matemáticas. Con ellas podemos utilizar estadísticos de frecuencias 
  • proporción
  • moda
  • coeficiente de contingencia
... y su representación gráfica principal es el diagrama de barras.

La escala ordinal permite establecer relaciones de orden entre los fenómenos, además de las relaciones de igualdad propias de la escala nominal, pero no es posible realizar operaciones con números, ya que la distancia entre dos posiciones no es necesariamente fija. A nivel ordinal es posible estudiar
  • valores máximos y mínimos
  • la mediana
  • los centiles
  • el rango intercuartílico
  • y las correlaciones ordinales
Aunque una escala de intervalo se diferencia de otra de razón en que la primera carece de valor 0 absoluto (lo que impide realizar operaciones de multiplicación y división), no es infrecuente que ambas sean tratadas como equivalentes, aplicando, en consecuencia, estadísticos
  • media o promedio
  • desviación típica
  • rango
  • varianza
  • coeficiente de variación
  • correlaciones

martes, 24 de diciembre de 2024

Lenguajes. R.

Datos y variables

Un lenguaje de orientación específica al análisis estadístico como es R presenta también una orientación específica al tratamiento de los datos con los que trabaja. Esto incide en qué tipo de datos considera y cómo los trata. Todo ello tiene implicaciones en el planteamiento de las variables y las colecciones de datos. En esta entrada hablaremos específicamente de las variables en R.


Los datos básicos de R son los siguientes:
  • Caracter (cadena de texto) (character) -> "La casa de la pradera" / "A"
  • Enteros (integer) -> 22
  • Decimal (numeric) -> 1.35
  • Factor (factor) -> uno
  • Lógico (logical) -> TRUE/FALSE
  • Perdido (NA) -> NA
  • Vacío (NULL) -> null
Además R también cuenta con otros tipos de datos como numéricos complejos (parte real y parte imaginaria), raw (byte), fecha y raster. De todos estos, posiblemente los más utilizados sean los datos de fecha.

La diferencia entre los datos integer y numeric es que los segundos son números con parte decimal, por lo que también se les conoce como  float (coma flotante).

La característica principal de los datos string/character es que van entrecomillados.

Un factor es un datos específico de R y se puede definir como un datos numérico que representa una etiqueta o nivel. Vg. 1 para masculino, 2 para femenino. Estos datos facilitan el ahorro de memoria del procesador.

Los datos NA y null son datos específicamente estadísticos. NA equivale a los datos perdidos y null representa la ausencia de datos. Ambos cobran sentido cuando trabajamos con tablas de datos complejas y permiten la identificación de esos tipos de "datos" y su tratamiento estadístico.

Los datos lógicos (TRUE/FALSE) permiten verificar si se cumple o no una condición determinada, facilitando el trabajo con al álgebra booleana.

Para conocer qué tipo de dato está asociado a una variable se usa la función class() (class(3)) que devuelve un string con el nombre del tipo de datos. También disponemos de la función is.TipoDato() (is.numeric(5)) que nos devuelve TRUE/FALSE.

En R se denomina coerción a la transformación de un tipo de dato en otro, y se realiza de forma implícita, del tipo de dato más restrictivo al nivel más flexible (lógico->entero->numérico->carácter) y no en orden inverso.

Para forzar explícitamente una determinada transformación empleamos la función as.TipoDato()

  • as.integer()
  • as.numeric()
  • as.character(
  • as.factor()
  • as.logical()
  • as.null()
  • ...

Si la conversión (coerción) está permitida, nos devuelve el dato convertido, pero si no lo está nos devuelve un aviso de error y el valor NA.



lunes, 28 de octubre de 2024

Lenguajes. Python.

Variables numéricas y operadores algebraicos


También python cuenta con tipos numéricos y los operadores algebraicos básicos necesarios para realizar las principales operaciones. En esta entrada trataremos de ambos.


Respecto a los tipos numéricos, al contrario que PseInt, y OOo Basic, en Python, al no ser necesario declarar previamente las variables (declaración implícita), en la asignación de valores o datos a las variables, no son necesarios nombres específicos para identificar los tipos de variables, aunque procesos de conversión o cambio de tipo revela que se pueden diferenciar tres conjunto numéricos (lo que equivale a decir que se identifican tres tipos numéricos: entero (Int), reales do de coma flotante (float) e complejos (números con parte imaginaria). Siguiendo la lógica de la teoría de conjuntos, los reales incluyen a los enteros y los complejos a los reales.

NOTARecuerda el gráfico de los conjuntos numéricos. En él se muestran los conjuntos y las relaciones que inclusión que rigen su relación. Los número complejos (conjunto C) incluyen los reales (conjunto R) y los imaginarios, por lo que constituyen el grupo más amplio de todos los conjuntos numéricos descritos por la ciencia matemática. Si estás interesado en conocer qué son los números imaginarios y las operaciones que se pueden realizar con ellas, te recomiendo que consultes este documento. También te recomiendo esta página.

A parte de simplificar el proceso de creación de variables y asignación de datos, la declaración implícita, cuando se trabaja con tipos numéricos, presenta en Python la ventaja añadida de que no existe incompatibilidad de tipos, desbordamiento o imprecisión por truncamiento cuando asignamos a una tercera variable el resultados de operar con otras. Es el propio intérprete el que se encarga de gestionar estas cuestiones (tipado dinámico), lo que nos evita tener que estar pendientes de cuestiones como las que comentamos respeto a los tipo numéricos y los operadores algebraicos en OOo Basic.

Te muestro una ejemplificación de lo anterior en estas comprobaciones realizadas directamente en el intérprete de Python (PyShell):

var1 = 23 

var2 = 32

var1+var2

55
var1 = 23
var2 = 34.54
var1+var2
57.54 

var1=23
var2 = 33
var3 = var1 + var2
print(var3)
56
var1 = 23
var2 = 3567.980
var3 = var1 + var2
print(var3)
3590.98

Observa que las primeras comprobaciones se realizan directamente y las segundas mediante la asignación del resultado de la operación a una variable. En azul el resultado que devuelve el intérprete.

Por lo que se refiere a los operadores algebraicos, Python cuenta con el mismo repertorio básico que se identifican en PSeInt y en OOo Basic, aunque varían algunos de los símbolos:

  • Suma (+)
  • Resta (-)
  • Multiplicación (*)
  • Potenciación (**)
  • División real (/)
  • División entera (//)
  • Resto (%)
Respecto a las dos modalidades de división (real y  entera) observa el resultado de aplicar los operadores /, // y % en Python, primero directamente...

var1 = 389

var2 = 23

var1/var2
16.91304347826087
var1//var2
16
var1%var2
21

... y en segundo lugar, asignando el resultado de la división a una variable:

vDivR = var1/var2
print(vDivR)
16.91304347826087
vDivE = var1//var2
print(vDivE)
16
vResto = var1%var2
print(vResto)
21

Como puedes ver, el resultado es el mismo, sin que se observen las diferencias de resultados en función del tipo de operación y variable. Esto supone una ventaja evidente sobre OOo Basic, y sobre otros lenguajes mucho más rigurosos en el tratamiento de los tipos numéricos. Y todo ello gracias el tipado dinámico.

Además de los operadores anteriores, Python dispone de unos operadores especiales llamados operadores aumentados de asignación. Son los siguientes (uno por cada tipo de operador básico):

  • += Suma asignación
  • -= Resta asignación
  • *= Multiplicación asignación
  • **= Potenciación asignación
  • /= División real asignación
  • //= División entera asignación
  • %= Resto asignación
Estos signos son equivalentes a lo que en otros lenguajes se expresa como asignación de operación a variable: a = a + x (siendo a la variable y x un número cualquiera). Por ejemplo:

a += 3 (Python) equivale a a = a + 3  (OOo Basic)

El resultado es una simplificación de la escritura del código, aunque para entender mejor su lógica, es necesario recordar que la asignación se realiza de derecha a izquierda, no de izquierda a derecha, por lo que la lectura de de la instrucción es la siguiente: el valor x (3), sumado al valor previamente asignado a la variable ase asigna a la misma variable a. El resultado es que ahora a = a+3.

Del mismo modo debemos entender el resto de las operaciones. Reproduzco a continuación la comprobación de estas instrucciones de asignación realizadas en el pyshell:

var = 5
print(var)
5
var+=3
print(var)
8
var-=3
print(var)
5
var*=3
print(var)
15
var**=3
print(var)
3375
var/=4
print(var)
843.75
var//=2
print(var)
421.0

Antes de dar por concluida esta entrada, me gustaría avanzar un poco más en el conocimiento del IDLE de Python y en su uso, ya que así es posible crear materiales de mayor complejidad. En concreto quisiera hablar de la diferencia entre el intérprete (Shell o PyShell) y el editor de código.

NOTA: Pyshell es el intérprete interactivo de comandos o instrucciones del IDLE que proporciona Python en su instalación. El editor de código, como su nombre implica, es una herramienta simple de escritura de texto, pero plenamente funcional para crear script.

Como vimos en una entrada anterior y en esta misma, podemos escribir código directamente en el intérprete del IDLE, pero hacerlo nos crea una importante restricción: únicamente podemos comprobar el funcionamiento de instrucciones sucesivas; aunque permite guardar el código generado durante nuestra sesión de trabajo (extensión .py) el resultado no es operativo, ya que necesitamos eliminar el texto identificativo inicial y los resultados de la propia ejecución de los comandos e instrucciones.

Cuando nos interesa guardar nuestro script plenamente funcional o desarrollarlo previamente para probarlo después como un todo, es necesario utilizar un editor de texto. Podemos utilizar cualquier editor, como el propio bloc de notas de Windows, pero el IDLE de Python cuenta con una aplicación orientada a este fin. Para acceder a ella deberemos...

Seleccionar el menú File del Shell y seleccionar...

  • New File, si queremos crear un nuevo script, u...
  • Open, si queremos acceder a un script ya creado.

diferencia del intérprete, el editor permite escribir el script para que sea interpretado posteriormente; también permite guardarlo (con extensión .py) y ejecutarlo a posteriori cuantas veces queramos (desde el menú Run). En principio, la ejecución se realiza en el intérprete (PyShell).

Finalmente, antes de dar por concluida esta entrada, incorporaremos la nueva funcionalidad del IDLE de Python e inauguraremos la creación de script en este lenguaje, aunque sea un script un tanto especial y limitado. Para ello te dejo acceso al "script" Python que contiene el conjunto de las comprobaciones que realizamos a lo largo de esta sesión. 

NOTA: Recuerda que, además de acceder a él, tienes que descargarlo, guardarlo en una carpeta de tu elección y acceder a él desde el IDLE de Python. Ya sabes cómo activarlo.

Lenguajes. Python.

Variables alfanuméricas (II)

Me ha surgido la necesidad de escribir líneas de código complejas formadas por string también complejos así que me he visto obligado a buscar una solución para crear un código legible a la vez que una salida por consola igualmente legible. 


Dado que esta situación puede darse con cierta frecuencia al manejar textos y variables alfanuméricas de cierta longitud y complejidad, me para que aportar soluciones de este tipo no es perder el tiempo en minucias, así que vamos a ver como podemos resolver este tipo de situaciones.

En primer lugar, cuando escribimos el código podemos acabar generando líneas de una elevada longitud que resultan difíciles de leer. Poder acotarlas ayuda a la lectura (y comprensión) de código.

Las soluciones son dos (al menos): acortar cada línea en una orden independiente o acortar la línea mediante un procedimiento que no genere error al intérprete. Un ejemplo:

Supongamos que queremos escribir lo siguiente como cadena de texto: 

"Dime la figura sobre la que quieres calcular el área. Para ello utiliza el siguiente código: C -> Cuadrado, R -> Rectángulo, T -> Triángulo, C -> Círculo"

Podemos perfectamente dividir el texto en dos partes, la primera informativa mediante la función print():

print("Dime la figura sobre la que quieres calcular el área. Para ello utiliza el siguiente código:")

... y la segunda mediante un input(), asociada a una variable para que cumpla su función (según se deduce de la configuración de la instrucción):

respuesta = input("C -> Cuadrado, R -> Rectángulo, T -> Triángulo, C -> Círculo")

De este modo evitamos crear una línea excesivamente larga que dificulta la lectura del código, aunque puede que la primera exceda, aun así, los márgenes aceptables para un código legible. Si así fuera considerado, bien podría dividirse en al menos dos print() diferenciados, solucionando así el problema:

print("Dime la figura sobre la que quieres calcular el área.")
print("Para ello utiliza el siguiente código:")

En términos de legibilidad del código, la solución es perfectamente válida, pero nos crea un ligero problema, poco relevante aquí, pero no tanto en programas de muchas líneas y cadenas de texto largas: necesitamos dos o tres instrucciones para resolver el problema. Si esto lo es, también podemos recurrir a otra solución aceptable para el intérprete Python: utilizar como separador de líneas que mantiene la integridad de código como una unidad (una sola orden):

    respuesta=input("Dime la figura sobre la que quieres calcular el área"\
                "Para ello utiliza el siguiente código:"\
                "C -> Cuadrado"\
                "R -> Rectángulo"\
                "T -> Triángulo"\
                "C -> Círculo")

La estructura creada gana en legibilidad y elegancia a cista de multiplicar la concatenación de segmentos (cadenas), pero tiene un problema: la salida (output) por pantalla no resulta funcional. Digamos que trasladamos el problema de la legibilidad al output (del programa), lo que dificulta el input (para el usuario)

Dime la figura sobre la que quieres calcular el área Para ello utiliza el siguiente código: C -> Cuadrado R -> Rectángulo T -> Triángulo C -> Círculo

Este problema (al menos en parte) ya lo habíamos podido observar en la versión primera del input(), pero ahora se revela en toda su extensión y resulta claramente inadmisible. Afortunadamente tenemos una solución: utilizar un salto de línea incorporado a cada string (\n). Esta opción produce el efecto deseado en la salida del programa (el salto de línea) allí donde se ubica, con independencia de la posición que ocupe en el string que escribimos como código. En este caso nos interesa la coincidencia del fin y salto de la línea de código con el salto de línea del output (en pantalla), pero esto es circunstancial.

    respuesta=input("Dime la figura sobre la que quieres calcular el área"\
                "\nPara ello utiliza el siguiente código:"\
                "\nC -> Cuadrado"\
                "\nR -> Rectángulo"\
                "\nT -> Triángulo"\
                "\nC -> Círculo"\
                "\nInicial de la figura: ")
   
Lo importante es que la combinación de ambos recursos (\ para separar líneas sin romper la unidad de la instrucción, y "\nString..." para generar saltos de línea en pantalla) nos permiten obtener un código legible (como el de arriba), a la vez que una salida por pantalla igualmente legible con una única instrucción input()

Dime la figura sobre la que quieres calcular el área
Para ello utiliza el siguiente código:
C -> Cuadrado
R -> Rectángulo
T -> Triángulo
C -> Círculo
Inicial de la figura:

jueves, 24 de octubre de 2024

Lenguajes. Python.

Variables, constantes y operadores.

Una variable es un identificador de una posición o contenedor de la memoria RAM en la que se almacenan datos a los que se puede acceder mediante la referencia a la variable o nombre identificativo. En función del tipo de contenido que se almacene en esa posición de memoria hablaremos de tipos de variables (numéricas, alfanuméricas o booleanas).



A diferencia de otros lenguajes, Python no precisa que las variables sean declaradas previamente, sino que la identificación se realiza en el momento en que se la nombre y se le asigna un dato. Otra característica específica de Python es que diferencia la variable según se escriba (case sensitive): vVar1 es una variable y vvar1 es otra variables distinta.

Otras condiciones que se deben tener en cuenta a la hora de dar nombre (identificador) a una variable es que no se pueden usar las palabras reservadas del lenguaje Python, que son las siguientes:

and  - as  - assert - break - class - continue - def - del - elif - else - except - finally - for - from - global - if - import - in - is - lambda - nonlocal - not - or - pass  - raise - return - try - while - with - yield - False - None - True

Las variables deben empezar por una letra, no por números, aunque los pueden contener. Lo que no pueden es contener caracteres que no sean alfanuméricos (a excepción del guion bajo, que se puede usar para unir dos palabras (var_prim)o una palabra y un número (var_1) ni espacios en blanco (var prim no es un nombre válido de variable, var_prim sí lo es).

Python no cuenta con constantes, pero por convención, las variables se escriben en minúsculas (ej. var1, var_1) y se reservan los nombres en mayúsculas para funcionar como constantes (ej. CONST1, CONST_1).

En consecuencia, la diferencia entre variables y constantes es, en Python, más funcional y de lógica de programación, que consustancial al lenguaje: una variable "contiene" (referencia a un contenedor RAM) datos (valores) que pueden cambiar; una constante, por el contrario, se mantendrá sin cambios a lo largo del algoritmo.

Para trabajar con las variables utilizamos los llamados operadores, en los que se diferencian tipos en función del tipo de variable. Así podemos hablar de operadores algebraicos o aritméticos, operadores alfanuméricos o de cadena, operadores booleanos y operadores de asignación.

Los operadores aritméticos son los siguientes:
  • + Suma (a+b = c
  • - Resta (a-b = d)
  • * Multiplicación (a*b = e)
  • / División (b/a = d.ddd)
  • // División entera (b//a = d)
  • % Resto (de la división entera) (b%a = e)
  • ** Potenciación (a**2 = a*a= f) (1)
Los operadores de cadena (string) son:
  • + Concatenación (literal) s1+s2 ("suma" ambas cadenas)
  • s1*n Multiplicador. s1*3 -> s1s1s1 (repite la cadena n veces)
Los operadores booleanos siempre devuelven True (V) o False (F):
  • > y >= Mayor (mayor o igual) que
  • < y <= Menor (menor o igual) que
  • and (Y lógico). a>b and b>c V si se cumplen ambas condiciones. F el resto.
  • or (O lógico). a>b or b>c. V se se cumple al menos una condición. F si no se cumple ninguna de las dos.
  • != Diferente a!=b.
  • == Igual que
Por último tenemos los operadores de asignación siguientes:
  • = Asignación (a = 3) (2)
  • += Asignación e incremento (a +=1 -> a = a+1)
  • -= Asignación y decremento (a -=1 -> a = a-1)
  • *= Asignación y producto (a*=2 -> a = a * 2)
  • /= Asignación y división (a/=2 -> a = a/2)
  • %= Asignación y resto (de división entera) (a%=2 -> a = a%2)
Ejemplos de uso de variables y operadores:

# Operadores aritméticos

3+4*(8-2)
27
45/7
6.428571428571429
45//7
6
7**2
49
43%7
1
45/7
6.428571428571429
45//7
6
45%7
3
2**2
4
2**3
8
2**4
16
2**5
32
2**1/2
1.0
24**2
576
576**1/2
288.0
576**(1/2)
24.0

#Operadores alfanuméricos (string)

"Hola"
'Hola'
"Hola " + "Julio y Juan"
'Hola Julio y Juan'
3*"Hola-"
'Hola-Hola-Hola-'
"Hola-" * 3
'Hola-Hola-Hola-'

#Operadores booleanos

>>> 7 > 9
False
>>> 7>5
True
>>> 7>=7
True
>>> 7>=6
True
>>> 7<5
False
>>> 7<8
True
>>> 7<=8
True
>>> 7==7
True
>>> 7<9 or 7<6
True
>>> 7<9 and 7<6
False
>>> 7<9 and 7<8
True
>>> 7!=5
True
>>> 7<9 | 7<6
False
>>> 7<9 & 7<8
False

# Operadores de asignación

>>> x = 5
>>> print(x)
5
>>> x +=1
>>> print(x)
6
>>> x -=1
>>> print(x)
5
>>> x *=2
>>> print(x)
10
>>> x /=2
>>> print(x)
5.0
>>> x %=2
>>> print(x)
1.0

NOTAS

(1) No existe símbolo operacional para la raíz, por lo que su cálculo debe realizarse a partir de la equivalencia conocida entre raiz y potenciación fraccional (24**2 permite calcular la raíz cuadrada de 24). En la lógica de los ejemplos de la entrada f**2 = a)
(2) Es importante tener presente que = es operador de asignación, no de equivalencia o igualdad, función que cumple el operador ==. La confusión puede venir dada por ser operador de asignación y de igualdad en otros lenguajes como OOo Basic.

viernes, 13 de septiembre de 2024

Lenguaje. Python.

Variables alfanuméricas (I)


Vamos a análisis ahora no el elemento alfanumérico más básico, que es el carácter, pero sí el que resulta ser el mínimo funcional para el trabajo con textos mediante Python: las cadenas alfanuméricas o string.


Las cadenas alfanuméricas son uno de los tipos de datos que podemos manejar con Python; así que empezaré por tratar con más detalle  las cadenas de caracteres (string, de ahora en adelante), tanto por su carácter básico como por el estatus que en realidad tiene que posiciona al string en una zona intermedia entre el dato y la colección de datos. Esto incrementa la complejidad de tratamiento, pero también ofrece un amplio conjunto de posibilidades de manejo en Python (1).

Ya sabemos que, al contrario que en otros lenguajes, en Python no es necesario declarar previamente de qué tipo es una variable (2), siendo suficiente con asignarle contenido para que quede realizado el tipado, que, además, se modificará en función de los cambios de contenido que pueda recibir la variable a lo largo del programa. En consecuencia, la asignación de contenido string a una variable en Python es tan sencillo como esto: VarSaludo = "Hola Mundo"Y es igual de sencillo para contenidos mínimos (un carácter) que máximos (un texto completo).

Precisamente por ello, disponemos en Python de determinadas funciones que nos permiten conocer de qué tipo es cada variable (3), una de ellas es la función type() (4). Usando esta función podemos apreciar el significado de Python como lenguaje de tipado dinámico:

var1 = "1"
print(type(var1))
<class 'str'>

Inicialmente asigno a var1 el dato alfanumérico "1" (var1 = "1") y mediante la función type() (print(type(var1))) obtengo información respecto a su categorización como string (<class 'str'>), pero si modifico el dato asignado a var1 (ahora como valor numérico -> var1 = 1), lo que me devuelve la type() es que la variable es (pertenece a la clase de tipo) integer (<class 'int'>).

En esta primera entrada me limitaré a tratar dos de los procesos implicados en el desarrollo de un algoritmo: la entrada o input y la salida o output. El procesamiento, que es la parte más compleja, requerirá diversas entradas, aunque la primera y más básica (al menos para lo que a nuestros objetivos ser refiere) es el encadenamiento de string, por lo que trataremos esta cuestión en breve.

Para en entrada (input) de datos, en Python empleamos la función input() (5), con la que obtendremos resultados diferentes en función del modo (directo o indirecto) en que usemos dicha función. Si la usamos directamente (input ("Nombre: ")) ...

input ("Nombre: ")
             
Nombre: Javier
'Javier'

... en el modo directo (desde el Shell) se producirá la ejecución de la instrucción, a la que responderemos (Nombre: Javier) y obtendremos como resultado nuestra respuesta entrecomillada ('Javier'), clara indicación de que el "programa" nos está devolviendo un dato de tipo string.

Pero si la empleamos indirectamente, esto es, asociada a una variable (vsNombre = input("Nombre: " )), también en el Shell, obtendremos como respuesta de ejecución la petición realizada (Nombre:), quedando el programa a la espera de nuestra respuesta (igual que antes), pero a diferencia del procedimiento anterior, una vez que respondemos a la petición de entrada de datos, el programa finaliza o queda a la espera de las siguientes instrucciones, esto es, no produce ninguna salida informativa como sí hizo antes.

Es este el momento en el que entra en acción la función output (salida) print() (print (vsNombre)), que produce aparentemente la misma salida, pero con una diferencia: ahora el string de respuesta no aparece entrecomillado (Javier). Esta pequeña gran diferencia está informando de que la respuesta no es informativa del sistema, es la continuación del programa mostrando la salida esperada en función del procesamiento del dato entrante que previamente hemos suministrado, procesamiento que ha realizado la función print().

Digo pequeña diferencia porque únicamente aparenta ser una cuestión de forma (con vs. sin comillas), pero en realidad es una diferencia grande, dado que afecta a la lógica del funcionamiento del código: quedar a la espera de una nueva instrucción implica solicitar continuidad del procesamiento, que en este caso se concreta como función de salida (print()) (6). Podemos considerar la combinación input() - variable - print() como la base del proceso de programación, esto es, de generación de un procedimiento basado en un algoritmo.

Otras formas de construir estos pequeños "programas" (7), empleando únicamente ambas funciones, es informar primero (mediante print()) de la demanda que sigue, y que se canaliza a través de input(), para devolver finalmente el resultado mediante (de nuevo) la función print():

print("Por favor, dime tu nombre:")

Por favor, dime tu nombre:

vsNombre = input()

Javier

print(vsNombre)

Javier

También podemos hacer uso del argumento end de la función print(), evitando así el salto de línea en el momento de la ejecución del programa (print("Por favor, dime tu nombre:"), end="")

De estas diferentes formas de trabajar con los procesos de entrada y salida, el más común es el primero, pero todos ellos no dejan de ser variaciones sobre el mismo procedimiento de escaso interés práctico; lo importante es que sobre ellas construiremos el trabajo con los textos, según iremos viendo en las entradas que siguen en esta sección.

NOTAS

(1) Un string es ciertamente un dato (una unidad de información) que podemos manejar como tal mediante su asignación o referenciación a una variable, pero también una colección de caracteres. Siendo como es el carácter el elemento mínimo de información del string, este se comporta (y se maneja) como colección de datos, más concretamente como lista, de ahí que en Python sea posible trabajar con el string como con una lista. En realidad, en términos de modelo de objeto, el string es una clase de objeto, por lo que en el trabajo con él podemos hacer uso de los métodos y los atributos que tiene asociados. De ahí la riqueza y la complejidad de presenta Python en el manejo de este tipo de dato.
(2) Recuerda lo explicado [en esta entrada] (pendiente) respecto a Python como lenguaje de tipado dinámico: la variable es del tipo del dato que se le asigne. En otros lenguajes, como en OOo Basic, podemos (y es conveniente) determinar a priori el tipo de dato que contendrá una variable antes de realizar la asignación (Dim sNombre As String) como paso previo para sNombre = "Javier"). Esta exigencia, al menos en algunos lenguajes, resulta conveniente, ya que evita errores de programación cuando el script es de cierta complejidad y extensión.
(3) Ya sabemos que lo correcto es decir qué tipo de contenido o dato está referenciado por una variable, ya que la variable no es otra cosa que un identificador, una clave, que facilita al lenguaje el acceso a una posición de memoria RAM en la que se almacena el dato; en este caso nuestro string. Pero, a riesgo de simplificar, en este blog emplearé expresiones como la anterior, ya que resulta más sencillo y se supone al lector el conocimiento teórico básico suficiente para no dar lugar a una confusión que, por otra parte, es poco relevante en términos operativos.
(4) Desde [este enlace] puedes acceder a una explicación más detallada sobre funciones y formas de conocer el tipo variable. En relación con la naturaleza de objeto que tienen los tipos de datos (entre ellos los string) es interesante la información que se aporta el enlace anterior respecto a las funciones dir() y __class__, que permiten conocer los atributos de cada clase-tipo de dato.
(5) input() devuelve siempre y por defecto un string, por lo que si trabajamos con datos de otro tipo deberemos convertirlos al tipo mediante las funciones correspondientes. Aquí, como estamos trabajando con string, esa conversión no es necesaria.
(6) El Shell también nos permite comprobar el funcionamiento de print() como función pura, siendo esta precisamente la forma básica y prototípica en que suele empezar todo aprendizaje de un lenguaje de programación (print("Hola mundo") -> Hola mundo). Obsérvese como la respuesta no está entrecomillada.
(7) Esto y lo que sigue tiene sentido más como parte del aprendizaje formal del lenguaje que utilidad práctica (en este sentido sólo aporta variaciones sobre el mismo tema) y es más propio de trabajo sobre la utilidad de escritura de código del IDLE que para su implementación directa en el Shell.

viernes, 26 de abril de 2024

OOo Basic. Datos

 Variables. Primeros pasos. (1)

Decía en una [entrada] que anterior que una macro creada con Grabar macro presenta una limitación insuperable en lo que toca a la personalización de los datos. Lo ejemplificaba con la personalización de un documento en términos de persona, lugar, fecha, área del currículo. En [otra entrada], de paso que aprendimos a identificar y usar variables, aprendimos también a superar esas limitaciones, precisamente usando variables. Este es el tema que ahora vamos a tratar en esta entrada y en las que la siguen.



Repito lo dicho: en programación, una variable no es un identificador de una dirección de memoria (RAM), un puntero que "apunta" a ese espacio de almacenamiento y, en consecuencia, al dato o datos que contiene.

Antes de hablar de los tipos de datos, recordemos las acciones previas que, de forma implícita o explícita, es necesario realizar para crear y dar funcionalidad a una variable.
  • En primer lugar deberemos declarar esa variable empleando en OOo Basic la expresión reservada Dim cuando lo hacemos de forma explícita.
  • En segundo lugar nombramos la variable, asignándole un nombre identificativo, respetando las reglas establecidas en el lenguaje. Es común el uso de expresiones alfanuméricas, lo más descriptivas posible. 
    • Se pueden nombrar como se desee, siempre que no sean palabras reservadas y no se inicie con símbolos coincidentes con los empleados como conectores o como  operadores.
    • Se recomienda iniciar con la inicial identificadora del tipo de variable en minúscula, bien en castellano (tNombre) o en inglés (sNombre), ambas para identificar una variable de tipo texto (string) destinada a la asignación del nombre del sujeto. 
    • Este modo facilita la identificación del tipo de variable, pero no implica la categorización tipológica.
En caso de que esa descripción implique el uso de varias palabras hay que recordar que deben ir juntas. En ese caso se utilizan dos procedimientos:
    • Unirlas mediante guion bajo (Var_Primera)
    • O escribirlo todo junto, poniendo en mayúscula la primera letra de cada palabra (VarPrimera)
  • En tercer lugar asignamos tipología mediante la expresión As Tipo (vg, As String, en el caso de sNombre)
  • Finalmente asignamos contenido (dato/s) a la variable, empleando para ello el operador de asignación, que en OOo Basic es el signo =
Ejemplificando el proceso explicado antes aplicándolo a la creación de una variable para contener el nombre de un alumno o alumna, el resultado sería el siguiente:

Dim sNombre As String (es equivalente dim sNombre as string)
sNombre = "Luis" (dado que se trata de una variable de tipo texto)

Cuando deseamos declarar varias variables del mismo tipo, podemos hacerlo en una misma línea:

Dim sNombre As String, sApellido1 As String, sApellido2 As String 

De lo visto hasta el momento se sigue lo que podemos llamar explicitación del proceso, pero cabe realizarlo de forma implícita. En OOo Basic ambas opciones están disponibles, aunque se recomienda utilizar la explícita por motivos de claridad de escritura del código.

De optar por esta alternativa es recomendable indicarlo mediante la expresión Option Explicit escrita antes de crear el primer script del módulo. De este modo se hace obligatoria la declaración y explicitación tipológica. En caso contrario, es suficiente con la asignación de datos para presuponer el proceso previo.

Como ejemplo aporto dos sencillos script (disponibles desde el IDE) [en este documento]. El primero funciona siempre que esté anulada (comentada) la expresión Option Explicit y el segundo funciona tanto si lo está como si está activa (no comentada).


NOTA

(1) Con fecha 26/04/2024 modifico la entrada original (12/06/2023) para ajustarla a la reformulación del esquema de contenidos actual de la página (apartado del blog) OOo Basic. En la modificación se incluye información relativa a las entradas que anteceden a ésta y se mantiene el resto del contenido de la original.

OOo Basic. Datos

Variables

Una orientadora, Mercedes, está colaborando con la Jefa de estudios del colegio elaborando informes escolares de una lista de alumnos y alumnas (el motivo ahora no es relevante). Mercedes piensa usar lo que estamos aprendiendo sobre LibreOffice y piensa crear un documento-base en Writer para elaborar los informes que recojan los datos de ese análisis. Veamos cómo lo podemos enfocar.


Después de investigar unos cuantos expedientes y una vez que se hace idea de cómo abordar el tema, Mercedes se plantea crear un documento-modelo para recoger toda la información. Hace un informe a modo de "ejemplo" y, después de revisarlo y reajustarlo, se plantea utilizarlo como base para construir los restantes. 

Aunque una Mercedes real posiblemente actuara de otro modo (1), nosotros vamos a suponer que quiere poner en práctica lo aprendido hasta ahora: crear macros y script.

Puesta a la tarea, Mercedes crea una primera macro a la vez que va escribiendo su documento. Supongamos que este texto es parte del inicio del documento:

Juan es actualmente alumno de 4º de E. Primaria en el C.P. Aurelia Sánchez (Santullano)

Activa Grabar macro, escribe el texto, finaliza la grabación, prueba su macro y observa que funciona según lo previsto. Pero ahora se le presenta un dilema: si quiere hacer ahora el informe de Luis se encuentra conque o utiliza su documento como documento-base y sustituye Juan por Luis o tiene que crear una macro para cada alumno. Evidentemente esta segunda opción no es razonable, ya que no le quita trabajo (2).

Supongamos que, a pesar de ello, crea una segunda macro, ahora con este otro texto:

Luis es actualmente alumno de 2º de E. Primaria en el C.P. Aurelia Sánchez (Santullano)

Comparemos ambos textos:

  • Observamos que varían dos datos: el nombre del alumno y el curso.
  • El resto permanece igual
Esos datos que varían (Juan - Luis y 4º - 2º) son las variables. Ambos pertenecen a dos conjuntos, el conjunto nombre y el conjunto curso, por lo que podemos entender que una variable, además de lo obvio (un dato que varía) también se puede entender como la denominación genérica de un conjunto de datos.

Pero desde la perspectiva de la programación, una variable es, en realidad, un identificador de un espacio de memoria RAM a cuyo contenido se accede utilizando ese identificador.

En todo caso, y con independencia de con qué conceptualización nos quedemos, usar variables nos va a permitir resolver de forma sencilla el problema de Mercedes: es suficiente con que sustituya el nombre concreto por un identificador como sNombre y el curso por sCurso para que no necesite cambiar en el texto ni el nombre ni el curso. Pero aun no sabemos cómo se hace eso.

Vamos a ver qué dice las macros que ha creado Mercedes. Para ello accedemos al IDE como sigue: 
  • Herramientas | Macros  | Editar macros.
  • Si no estamos ya en nuestro documento, Biblioteca Standard, Módule1 (por ejemplo), repetimos la selección que implica llegar hasta aquí...
  • Y nos encontramos con el código siguiente:

sub InfoEscolar1
rem ----------------------------------------------------------------------
rem define variables
dim document   as object
dim dispatcher as object
rem ----------------------------------------------------------------------
rem get access to the document
document   = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")

rem ----------------------------------------------------------------------
dim args1(0) as new com.sun.star.beans.PropertyValue
args1(0).Name = "Text"
args1(0).Value = "Juan es actualmente alumno de 4º de E. Primaria del C.P. Aurelia Sánchez (Santullano)"

dispatcher.executeDispatch(document, ".uno:InsertText", "", 0, args1())

end sub

sub InfoEscolar2
rem ----------------------------------------------------------------------
rem define variables
dim document   as object
dim dispatcher as object
rem ----------------------------------------------------------------------
rem get access to the document
document   = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")

rem ----------------------------------------------------------------------
dim args1(0) as new com.sun.star.beans.PropertyValue
args1(0).Name = "Text"
args1(0).Value = "Luis es actualmente alumno de 2º de E. Primaria del C.P. Aurelia Sánchez (Santullano)"

dispatcher.executeDispatch(document, ".uno:InsertText", "", 0, args1())

end sub

Tenemos dos macros (Sub InfoEscolar1 y Sub InfoEscolar2) que son exactamente iguales, a excepción de la diferencia de nombre y curso que ya identificamos antes. Poca opción nos da esto para ahorrar tiempo. ¿Cómo podemos usar variables en este caso?.

Con el tiempo aprenderemos que una macro en realidad  hace uso de variables, pero por ahora las que emplea no nos resuelven el problema. Y esta es la principal limitación de las macros, motivo por el que necesitamos aprender a trabajar con OOo Basic, incluso para mejorar (y simplificar) el uso de macros.

Como ya sabemos crear un script en OOo Basic, en esta entrada vamos a avanzar lo suficiente para resolver el problema a Mercedes:
  • A continuación de la expresión dim dispatcher as object vamos a crear una línea en blanco (Intro) (en realidad dos líneas).
  • Y escribimos Dim sNombre As String en la primera y Dim sCurso As String en la segunda (3). Ya tenemos creadas nuestras variables.
  • A continuación buscamos línea...

args1(0).Value = "Juan es actualmente alumno de 4º de E. Primaria del C.P. Aurelia Sánchez (Santullano)"

  • Y sustituimos  "Juan es actualmente alumno de 4º de E. Primaria del C.P. Aurelia Sánchez (Santullano)" por sNombre & " es actualmente alumno de " & sCurso & " de E. Primaria del C.P. Aurelia Sánchez (Santullano)" (es importante respetar el uso de las comillas y los espacios iniciales)
Con esto la segunda macro ya no es necesaria, así que la podemos borrar.

Mercedes dispone ya de variables en sustitución de los datos (nombre y curso), pero aun no puede sacar todo el partido posible de su descubrimiento: necesita un medio para introducir los datos concretos (Juan y Luis, por ejemplo). Para ello tiene que aprender a dar valor (asignar contenido o datos) a las variables, para ello...
 usar una función OOo Basic llamada InputBox(), asociándola a cada una de sus variables. Vemos cómo.
  • A continuación de Dim sCurso As String generamos un salto de línea (mejor dos para que el código sea más visible) y escribimos estas dos líneas:

sNombre = "Juan"
sCurso = "4º" 

Con ellas estamos diciendo a OOo Basic que almacene en el espacio de memoria RAM identificado como sNombre el dato "Juan", de modo que cuando aparezca la expresión sNombre acceda a ese espacio de memoria, recupere su contenido (el dato "Juan" en este caso) y haga con él lo que corresponda (en nuestra "macro" escribir Juan antes de la cadena " es actualmente..."). Y lo mismo con sCurso.

Usar este procedimiento no es la mejor opción posible, ya que obliga a Mercedes a acceder al IDE y realizar las asignaciones pertinentes para cada informe, así que mejor buscamos otra solución más funcional: usaremos la función OOo Basic llamada InputBox(), asociándola a cada una de las variables. Vemos cómo:

  • Sustituimos  sNombre = "Juan" por sNombre = InputBox("Nombre del alumno"
  • Y hacemos lo mismo con sCurso
Ahora Mercedes ya no tiene que acceder al IDE, es suficiente escribir el nombre (y el curso) del alumno en espacio disponible en la ventanita emergente que genera la función InputBox() y que tendrá a su disposición de forma automática una vez que llame a la macro (Herramientas | Macros | Ejecutar macro)

Aunque parezca poco, en esta entrada hemos avanzado mucho:
  • Hemos accedido a una macro e identificado en ella la información que nos interesa.
  • Hemos aprendido a crear (declarar) y usar (asignar valor y sustituir el dato concreto por la variable) variables.
  • Y hemos automatizado y generalizado la creación de un documento combinando una macro con unas variables, lo que equivale a decir que hemos aprendido (de momento empezado a aprender) cómo superar las limitaciones de las macros mediante su tratamiento con OOo Basic.
  • Además hemos utilizado una función que facilita la fase Input del proceso básico de un script (Input - Procesamiento - Output) (4)
Evidentemente lo aprendido hasta ahora sobre las variables no es más que el principio, pero en las entradas que siguen seguiremos aprendiendo mucho más sobre ella. Por el momento te dejo para que descargues el documento [loPrimero.ods] con la macro modificada (InfoEscolar) según los pasos seguidos en esta entrada para que puedas estudiarla y crear tú las réplicas que te parezca (5).

NOTAS

(1) Una Mercedes real posiblemente se quedara aquí y se limitara a marcar los espacios de los datos que varían, manteniendo el resto del contenido, a modo de texto mutilado. No es mala opción y a la altura del proceso de aprendizaje en que nos movemos es posible que incluso sea la mejor opción. Excepción hecha del uso de la funcionalidad Combinar correspondencia, siempre que el documento no sea muy complejo. De todos modos (posiblemente sin saberlo) Mercedes está trabajando "manualmente" con variables (y constantes). No obstante nosotros vamos a darle más recorrido el tema y hacerlo un poco más complejo. Complicar lo sencillo es, a veces, una buena forma de aprender. 

(2) En realidad, aun en esta caricaturización de la situación crear una macro sí supone un ahorro de tiempo. Si el documento tiene cierta extensión, se aprecia la ventaja (relativa, pero real) que tiene Grabar macro: crear una macro que le dé forma y contenido evita tener que escribirlo todo desde cero. También es más estable, seguro y manejable que trabajar con un documento-modelo. Es necesario, eso sí, utilizar (por ejemplo) Editar | Buscar y reemplazar para ir modificando los datos que varíen (quedémonos con esto: datos que varían)

(3) También podemos escribir Dim sNombre As String, sCurso As String, pero por ahora nos interesa diferenciar ambas expresiones. Además seguramente habrás pensado que "alumno" no es un término correcto cuando tengamos que hacer el informe de Rosa, con lo que también podría ser considerada una variable. Pero, por didáctica nos limitaremos a las dos variables dichas.

(4) Como sin duda Mercedes es inteligente, se habrá dado cuenta además que, limpia de texto irrelevante, la sintaxis de la macro le permite crear todos los textos que se imagine, siendo suficiente con sustituir el párrafo de nuestra macro por cualquier otro texto, el cual puede haber creado previamente (copiar y pegar) o crearlo directamente sobre en el IDE. Esto incluye el uso de todas las variables que le interese. Sólo necesita copiar la macro, cambiar su nombre (Sub NuevoNombre) para no perder la macro original y realizar en args1(0).Value = a sustitución que propuse antes. Y todo ello sin necesidad de usar de nuevo Grabar macro. Eso sí que es un ahorro de tiempo.

(5) Para mayor claridad del ejemplo he borrado de la macro original todos los comentarios, que ahora son innecesarios, aunque es buena praxis comentar el código. Ya aprenderemos cómo. Originalmente esta macro se llamaba InfoEscolar1, pero como ahora no necesitamos crear una macro por cada informe que queramos crear, pasa a llamarse InfoEscolar.