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

sábado, 13 de septiembre de 2025

Lenguajes. Python.

Funciones de cadena en Python: división y unión de elementos


Para separar y unir los elementos que componen una cadena de texto Python dispone de algunas funciones específicas que facilitan esta tarea. Dedicaremos entra entrada a experimentar con esas funciones que tanta utilidad van a tener en la automatización del trabajo con textos.


Vamos a empezar por la segmentación de una cadena, proceso en el que empleamos la función split(). Esta función nos permite dividir una cadena en segmentos en función de un separador (el que nosotros decidamos), que en caso de no especificar ninguno será directamente el espacio que separa las palabras. Un ejemplo.

Supongamos el siguiente texto asignado a la variable:

texto = "Una narración breve en prosa es un texto corto que cuenta una historia usando el lenguaje no métrico o rítmico, y que puede ser un cuento, un microrrelato o una fábula\n. Estas formas literarias se caracterizan por su concisión y la condensación de eventos en un formato limitado, buscando captar la atención del lector mediante la intensidad de la historia, un final inesperado o una enseñanza moral." 

Tomando este texto como objetivo, vamos a analizarlo en términos de posible segmentación. 
  • En primer lugar, podemos dividirlo en función de las palabras (lista1); para ello emplearemos split() sin determinar separador (lista1 = texto.split())
  • La segunda división puede ser dividirlo en función del punto (lista2), para lo que explicitaremos el elemento divisor (lista2 = texto.split('.'))
  • En tercer lugar, podemos dividir el texto en función del salto de línea (\n), que equivale a los párrafos que componen el texto. En este caso tenemos dos opciones (el resultado es el mismo):
    • Mediante la identificación directa del separador (lista3 = texto.split('\n'))
    • O mediante el uso de la función splitlines() (lista4 = texto.splitlines())
Podemos obtener un resultado confirmatorio de la ejecución de las diferentes instrucciones obteniendo el número de elementos de las distintas listas (v.g. n_pal = len(lista1)n_seg = len(lista2)) y mostrar a continuación el resultado de len() por pantalla (v.g. print (f'Número de elementos de la lista 1 ->  {n_pal}')), o también puedes hacerlo mostrando directamente los diferentes segmentos de las distintas listas mediante un bucle que las recorre:

i = 0
for i in range(n_pal):
    print(lista1[i])

Pasemos ahora a explicar el proceso inverso, consistente en unir lo que hemos separado previamente. Para ello disponemos de dos procedimiento que explico a continuación.

La primera forma consiste en utilizar un bucle cuya expresión más simple (pero no la única) es la siguiente, que incluye declaración de variables y escritura del resultado por pantalla:

i = 0
texto_1 = ""
for i in range(n_pal):
    texto_1 = texto_1 + lista1[i] + ' '
print(texto_1)

El núcleo de este procedimiento es la asignación recursiva del contenido de la lista sobre la variable contenedora (texto_1 = texto_1 + lista1[i] + ' ')

La segunda fórmula se basa en el uso de la función join()  que  nos ahorra el bucle y cuya sintaxis es la siguiente...

variable_de_asignación_de_cadena =  "separador".join(lista)

... que traducido a un caso concreto se muestra como sigue (incluyendo declaración de variable contenedora e instrucción de escritura por pantalla:

texto1 = ""
texto1 = " | ".join(lista1)
print(texto1)

domingo, 10 de agosto de 2025

Textos. OOo Basic

Cambio de género de palabras


Casi a modo de ejercicio te propongo en esta entrada un script que nos permite modificar el género de una palabra, pasando del masculino al femenino cuando se cumple la regla m(o) -> f(a). Se trata de una aplicación práctica de las funciones de [segmentación de cadenas] que he aplicado como opción de automatización de la composición de textos [en otro proyecto], y que me ha parecido útil explicar específicamente en esta entrada.


Es importante insistir en que es una solución interesante de automatización, pero limitada, tanto como lo es como solución la aplicación de normas gramaticales debido a su complejidad y a las excepciones que presentan.

Sub CambioGenPal

Dim Pal As String, Seg As String, PalAlter
Dim letra As String
Dim nL As Integer

Pal = "alumno"
Letra = Right(Pal,1)
nL = Len(Pal)
Seg = Left(Pal,(nL-1))

MsgBox (Pal & " - " & Letra & Chr(13) & "Número de letras de la palabra " & nL & Chr(13) & "Resto de la palabra " & Seg)

If Letra = "o" Then
PalAlter = seg & "a"
MsgBox "Palabra en masculino: " & Pal & Chr(13) &_
       "Palabra en femenino: " & PalAlter
ElseIf Letra = "a" Then
PalAlter = seg & "o"
MsgBox "Palabra en femenino: " & Pal & Chr(13) &_
       "Palabra en masculino: " & PalAlter
End If

End Sub

El objetivo que se persigue con este script es devolver la palabra en el género opuesto al de la palabra dada. El requisito es que este par de palabras se rijan por la oposición de género m(o) -> f(a).

Para realizar esta transformación hacemos uso de las funciones de segmentación de las cadenas de caracteres [vistas en esta entrada], concretamente de la función Right() y de la función Left() (1), la primera para obtener el carácter final y la segunda para obtener el resto de los caracteres que contiene la palabras (2).

Una vez aplicadas estas funciones, atendiendo a cual sea el genero de la palabra original y condicionando la respuesta a este dato (If Letra = "o" Then), se reconstruye la palabra mediante concatenación (vg. PalAlter = seg & "a"), ofreciendo la alternativa de género a la original.

NOTAS

(1) También hacemos uso de la función Len() que nos permite conocer el número de caracteres de una cadena.
(2) La primera acción nos permite comprobar que se cumple el criterio de base, aunque aquí no se considera otra alternativa, además de dar información sobre de qué carácter se trata. La segunda requiere conocer previamente en número de caracteres de la palabra (función Len(), ver 1) y servirá para recomponer y modificar la palabra a devolver por el script.

lunes, 28 de octubre de 2024

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:

martes, 15 de octubre de 2024

Lenguajes. Python.

Segmentar cadenas

Siguiendo con el interesante mundo de las cadenas en Python, después de la revisión de opciones de concatenación que hice en una entrada anterior, deseo en ésta revisar las principales funciones de que disponemos para manejar y formatear el contenido de las cadenas. La importancia de estos contenidos deriva de la propia del uso de cadenas en la automatización de documentos.


Enumero aquí las principales funciones, ejemplificando su modo de uso, empezando por len().

La función o método len() permite conocer el número de caracteres que contiene una cadena; esto es, devuelve el entero de dicho valor,. En este recuento incluye los espacios que separan las palabras (en caso de tratarse de un string con varias palabras)  y los signos de puntuación, que son considerados por len() también como caracteres.

print(len('Hola'))        -> 4
print(len('Ho la'))       -> 5 
print(len('¡Hola!'))      -> 6

Este método (len()) también evalúa variables que referencian string

print(len('Maria')              -> 5

nom = 'Maria'
print(len(nom))                 -> 5

y admite concatenación de literales y variables

cad1 = 'Los verdes prados de Oviedo'
print('La cadena ' , cad1 , ' tiene ' , len(cad1), ' caracteres')

así como diferentes procedimientos de concatenación

print(f'La cadena {cad1} tiene {len(cad1)} caracteres')
print('La cadena {} tiene {} caracteres'.format(cad1,len(cad1)))

Si len() permite identificar el número de elementos de una cadena es porque una cadena se comporta como una lista de caracteres, motivo por el que cada carácter tiene asociado un índice en el string mediante el cual es posible acceder al carácter. Así, por ejemplo, para cad1

print(cad1[0])        -> L (primer elemento del string asignado a cad1)
print(cad1[-1])        -> o (último elemento del string asignado a cad1)

Obsérvese  que, en orden directo, la matriz de elementos se inicia en 0 y que los índices negativos permiten acceder a los elementos de la cadena en orden inverso. Esta cualidad de la cadena como lista de caracteres y el uso de funciones de formato pueden ser de gran interés para la manipulación de segmentos de cadena. Tendremos ocasión de verlo con más detalle en una entrada que complemente a esta.

Ahora ya sabemos que una cadena se puede descomponer en una lista de caracteres, que la función len() nos permite conocer cuántos son estos y que podemos acceder a cada uno de ellos solicitándolos por su índice. 

Estos conocimientos son muy interesantes y es posible darles utilidad en el desarrollo de algoritmos de automatización de documentos. Pero no son las únicas utilidades que pueden tener utilidad en este ámbito de uso... ni en otros. Me estoy refiriendo en concreto a la utilidad que pueden tener dos métodos de trabajo con los componentes de una cadena: split() y join() 

Método split() permite identificar los segmentos de una cadena, no los caracteres que la componen, sino las subcadenas en que se divide. Su sintaxis básica es la siguiente:

cadena.split(sep,maxsplit)    donde...

    • cadena es la cadena o variable string sobre la que se aplica split()
    • sep es el argumento que identifica el carácter por el que se divide la cadena. Por defecto es el espacio (' ').
    • mxsplit es el argumento que establece el número de veces en que deseamos dividir la cadena (o número de apariciones de sep que deseamos utilizar como referente para separar las subcadenas). Por defecto su valor es -1, que indica que deseamos utilizar todas las apariciones del carácter sep  

Veamos algunos ejemplos utilizando cad1="Los verdes prados de Oviedo" 

divide_cadena = cad1.split()
print(divide_cadena)                  (1)  -> ['Los', 'verdes', 'prados', 'de', 'Oviedo']
divide_cadena = cad1.split(' ',2)
print(divide_cadena)                  (2)  -> ['Los', 'verdes', 'prados de Oviedo'] 
divide_cadena = cad1.split('d',-1)
print(divide_cadena)                  (3)  -> ['Los ver', 'es' pra', 'os de Ovie', 'o']

  • La formulación 'por defecto'  (1) divide la cadena en las palabras que forma la frase.
  • Cuando modificamos el parámetro mxsplit (2) obtenemos un número diferentes de secuencias. Concretamente 2 divide la cadena en tres partes: las resultantes de las dos primeras apariciones de sep (' ') ['los'] y ['verdes']  y el resto de la cadena ['prados de Oviedo']
  • Si utilizamos otro criterio para sep (en 3 -> 'd'), manteniendo mxsplit por defecto (-1), obtenemos segmentos identificados en función de la aparición del carácter sep

Por eso dije subcadenas y no palabras, aunque es posible que, al menos inicialmente el uso más frecuente sea el establecido por defecto, esto es, la creación de la lista de las palabras que forman la frase.

El resultado 'normal' del método split() nos da acceso a una lista que va a sernos de mucha utilidad cuando queramos modificar el contenido de esa lista. Utilizaremos para ello lo que sabemos respecto al manejo de listas: acceso a elementos, sustracción, adición y sustitución de elementos... Pero es posible que esto sea tema para tratar en otra entrada, así que mejor completamos la actual hablando del método join()

El método join() sirve para invertir los efectos del método split(), esto es, para unir los elementos diferenciados de una lista en una única cadena. Veamos cómo:

divide_cadena = cad1.split()             1-> Divide la cadena cad1 y asigna divide_cadena
unir_cadena=' '.join(divide_cadena)  2-> Une divide_cadena y asigna a unir_cadena
print(divide_cadena)                        3-> ['Los', 'verdes', 'prados', 'de', 'Oviedo']
print(unir_cadena)                           4-> Los verdes prados de Oviedo

Si en vez de 2 escribimos el método join() precedido de '__' , obtendremos en 4 el siguientes resultado: Los__verdes__prados__de__Oviedo.

Lenguajes. Python.

Concatenar cadenas (II)

No es esta la primera vez que hablo de cadenas y de las formas de concatenación disponibles en Python, pero la revisión de lo hecho y el estudio del tema me han convencido de la necesidad de tratar de nuevo esta cuestión, profundizando más en ella y analizando con cierto detalle los diferentes modos en que se planea este procedimiento de generación de código. La importancia que tiene en procesos de automatización documental justifica sobradamente que preste especial atención al tema.


Tampoco es sobre Python el único lenguaje respecto al cual trato el tema de la concatenación, ya que también dediqué alguna que otra entrada para tratar el tema tanto respecto a las funciones nativas de LibreOffice-Calc como en el lenguaje OOo Basic. De hecho, si vuelvo ahora sobre esta cuestión en Python es precisamente a consecuencia de haber trabajado sobre el mismo tema tomando como referencia el servicio LO-Calc.

Es posible que, al retomar el tema, se produzcan repeticiones de contenido que tal vez depure en una posterior revisión del conjunto de las entradas, pero que ahora sólo puedo lamentar como consecuencia lógica del paso del tiempo y de la complejidad de la temática. Te ruego disculpas, lector, por la molestia que esta repetición te pueda suponer.

Como vimos, en OOo Basic se utilizan dos formas básicas y se puede decir que intercambiables de concatenar cadenas: mediante + y & podemos concatenar tantos segmentos de texto y/o variables como deseemos, sin más límite que la extensión del párrafo que queramos crear y la inteligibilidad del código resultante, a cual, al ser un proceso repetitivo puede ser poco elegante, pero no necesariamente disfuncional o ininteligible.

Recuerdo que en su momento recomendé utilizar en OOo Basic & para concatenar string (y variables string) y reservar + para la operación de sumar, como forma de facilitar la lectura del código, pero se trata de una opción y preferencia personal, sin que exista (que yo sepa) motivación técnica específica para defender esta opción.

Vimos en una entrada anterior que en Python también podemos concatenar cadenas de forma directa mediante , y +, pero presentan limitaciones y restricciones que no se observan en OOo Basic, por lo que son fórmulas no recomendables en cuanto la combinación de cadenas adquiere cierto grado de complejidad, siendo para ello suficiente con que queramos combinar string literal con variables.

Dado que Python es un lenguaje en desarrollo, las versiones que se han ido creando con el paso del tiempo han ido incorporando soluciones diferentes y dejando atrás como obsoletas las que se mostraron limitadas, aunque no por ello dejan de estar disponibles, como pasa con los modelos básicos anteriores.

El último desarrollo en estas funcionalidades son las llamadas cadenas f, de las cuales ya te hablé en esta entrada, pero es posible que dejara por el camino procedimientos interesantes y aun vigentes que surgieron en su momento como respuesta a las demandas del procedimiento. Trataré en esta entrada de tapar estos huecos.

Todo esto es para confirmar que el tema de la concatenación de cadenas ya ha sido tratado en este blog, pero, una vez dicho, paso a indicar que, lo que sigue constituye una reformulación sistemática y ampliada de lo que esas entradas pueden haber recogido, a la vez que una continuidad y conclusión de lo explicado respecto a LibreOffice y OOo Basic en otro blog.

Así que paso a exponer paso a paso el análisis de las diferentes formas de concatenar cadenas en Python. Tomo como referencia lo que expone Alfredo Sánchez Alberca en su material on-line Aprendiendo con Alf, al que remito y del que me declaro deudor.

Expongo en primer lugar diferentes formas de uso de conectores [, y +], que son las formas equivalentes a lo que en OOo Basic son [& y +] respectivamente (1).

Primera formulación. Concatenación de dos literales con separación de coma (,).

print("Hola","Javier") -> Hola Javier

Segunda formulación. Concatenación de literal y variable con separación de coma (,).

nom = "Javier"
print("Hola",nom) -> Hola Javier

Tercera formulación. Concatenación de dos variables con separación de coma (,).

sal = "Hola" 
nom = "Javier"
print("Hola",nom) -> Hola Javier

Cuarta formulación. Concatenación de dos literales con separación de signo (+).

print("Hola"+"Javier") -> HolaJavier

Quinta formulación. Concatenación de literal y variable con separación de signo (+).

print("Hola"+nom) -> HolaJavier

Sexta formulación. Concatenación de dos variable con separación de signo (+).

print(sal+nom) -> HolaJavier

Séptima formulación. Concatenación de literal string y literal numeral con coma (,)

print("Número",123) -> Número 123

 Octava formulación. Concatenación de literal string y literal numeral con signo (+)

print("Número"+123) -> [TypeError: can only concatenate str (not "int") to str]

print("Número" + str(123)) -> Número 123

En segundo lugar vamos a explicar el uso de la primera fórmula de formateo de cadenas que se empleó en Python desde sus primeras versiones como lenguaje de programación. Se base en el uso del signo %s, siendo % el operador que hace de marcador y la referencia a la cadena que se anexa.  %s que se sitúa necesariamente dentro de la cadena en la posición en la que se desea ubicar el segundo segmento de la cadena y se puede utilizar tantas veces como sea necesario en combinaciones complejas. En estos casos la concatenación utiliza también los signos de las configuraciones ya vistas, especialmente el signo [,]. 

Al igual que los concatenadores [, y +] presenta también varias formulaciones, que enumeraré siguiendo el orden ya establecido (2)

Novena formulación. Literal cadena con unión de segundo elemento (cadena).

print('Hola, me llamo %s' % 'Javier') -> Hola, me llamo Javier

Décima formulación. Literal cadena con unión de segundo elemento (número).

print('Número %s' % 123) -> Número 123 

Undécima formulación. Literal cadena con unión de variable.

nom = 'Javier'
print('Hola, me llamo %s' % nom) -> Hola, me llamo Javier 

Décimo segunda formulación.  Fórmulas mixtas y complejas.

A. print('Hola %s' % nom,',buenos días') -> Hola Javier, buenos días

B. print('Hola %s','buenos días' %nom) -> TypeError: not all arguments converted during string formatting

C. print('Hola %s', buenos días', %nom) -> Hola Javier, buenos días

D. print('Hola %s' % nom,',buenos días') -> Hola Javier, buenos días

E. annos = 24
    print('Hola %s' % nombre, ', tienes %s' % annos , 'de edad (eso quisieras)') -> Hola      Javier, tienes 24 años de edad (eso quisieras)

F. print('Hola %s, tienes %s' % nom % annos, 'de edad (eso quisieras)') ->TypeError:       not enough arguments for format string

Lo que revela esta formulación (y sus variantes) es que es posible concatenar más de una cadena (o componente, ya que también es válido para números y para variables) siempre que se respete la sintaxis de %s que obliga a:

  • Posicionar el marcador en la posición requerida por la formulación deseada de la cadena resultante de la concatenación (A)
  • Uso de tantos marcadores como sea necesario en función de lo deseado (C, E)
  • Pero con restricción de posicionamiento: cada uso de %s debe posicionarse tras la cadena afectada (B,D) y señalar sin ambigüedad a un contenido a anexar, no admitiendo dos marcadores dentro de una subcadena ni dos referencias sucesivas (F)
A pesar de la sencillez de este procedimiento, ya podemos advertir que su utilidad supera ampliamente los recursos disponibles en OOo Basic en cuanto al manejo de cadenas. Gracias a esto es posible idear procedimientos de personalización de documentos basados en la técnica 'cloze': sobre un texto base, los contenidos a personalizar son asumidos por variables, las cuales, a su vez, son cumplimentadas por el usuario de modo interactivo mediante la función input (ver ejemplo). Y no acaban aquí las opciones.

Efectivamente, una tercera opción (o procedimiento, si se prefiere) de formateo de cadenas es el método cadena.format(valores):
  • La posición de los valores en la cadena-base se identifican con {}
  • Esta cadena se sitúa al inicio de la secuencia
  • El texto de reemplazo va precedido de la id de a función format()
  • ... y se puede hacer por posición de forma implícita o explicitando los valores posicionales...
  • ... o bien utilizando la forma diccionario clave:valor
Veamos ejemplos prácticos de todo ello (3)

Primera forma.

print('Me llamo {}, vivo en {} y estudio {} en {}'.format('Elvira','Oviedo','Veterinaria', 'León.))

-> Me llamo Elvira, vivo en Oviedo y estudio Veterinaria en León.

 Segunda forma.

print('Dame {}, el {} y los {}'.format('la llave inglesa', 'destornillador', 'alicates'))
print('Dame{2}, la {0} y el {1}'.format('llave inglesa', 'destornillador', ' los alicates'))

El texto resultante de 2.1 será  Dame la llave inglesa, el destornillador y los alicates y el de 2.2 Dame los alicates, la llave inglesa y el destornillador.

Tercera forma. Uso de variables (4).

 

nombre = 'Julia'
localidad = 'Gijón'
estudios = 'Albañilería'

print('Me llamo {}, vivo en {} y estudio {}'.format(nombre,localidad,estudios))

print('Me llamo {1}, vivo en {2} y estudio {0}'.format(nombre,localidad,estudios))

Cuarta forma.  Clave:Valor (5)

print('Me llamo {nom}, vivo en {local} y estudio {estud}' .format (nom=nombre, local=localidad, estud=estudios))

Finalmente, la cuarta opción ya ha sido específicamente tratada en una entrada de este blog, por lo que no me detendré demasiado en ella. Se trata de las llamadas cadenas f (f-string o formatos literales), que se caracterizan porque su sintaxis incluye F o f al inicio de la cadena, en literales, antes de las comillas. Veamos un ejemplo (6):

nom1 = 'Juana'
nom2 = 'Lucas'
print(f'Una niña llamada {nom1} juega con un niño llamado {nom2}')

print(f'{nom1}') -> Juana

Contamos aun con una última forma de concatenar variables con cadenas, aunque esta quinta opción es en realidad una opción que podemos considerar complementaria de las anteriores, ya que no forma parte de los recursos comunes del lenguaje y precisa importar una librería específica llamada Template y las funciones asociadas a string

 from string import Template

print(Template('Me gusta estudiar $leng').substitute(leng='Python'))

print(Template('Me gusta $accion $leng').substitute(accion='estudiar', leng='Python'))

Puedes observar en estos dos ejemplos la sintaxis del procedimiento, en cierto modo recuerda al uso de funciones y más específicamente a .format():

  1. Primero llamamos a la función Template()
  2. Después incluimos dentro de cadena los marcadores, que se identifican mediante la expresión $NomVar.
  3. Y finalmente, mediante la función .susbtitude(), como parámetros de ellas en, y en formato clave:valor, damos contenido a las variables.

NOTAS

(1) Ambas fórmulas funcionan igual (salvo en determinados casos) siendo los contenidos string, con la única diferencia que el uso de coma (,) genera un espacio de separación entre los componentes, mientras que el uso del signo más (+) no lo genera. Este caso es necesario implementarlo como parte del literal o como cadena formada por un espacio (' ' o " ") y posicionada entre los demás componentes. Uno de los casos en los que (,) y (+) no funcionan igual es cuando queremos combinar texto y números dentro de la concatenación. En ese caso mientras que podemos hacerlo sin problemas si usamos (,) (como en Séptima), no funciona si usamos (+) (como en Octava). En ésta opción debemos convertir el número antes a string mediante la función str().
(2) En los tres casos el funcionamiento el correcto y el uso y posicionamiento del %s sigue el mismo patrón (se sitúa al final del primer literal), lo es debido al tipo simple de concatenación, pero no responde a una exigencia de la sintaxis de código.
(3) Las llaves {} indican la posición de los valores de .format(). Tanto en la primera forma como en la primera línea de código de la segunda, aunque no se especifica nada dentro de las llaves, es el orden mismo en que aparecen los valores .format() el que sirve para indicar la posición que ocuparán en el texto. LO que hago con la segunda línea de código de la segunda forma es alterar ese orden indicando dentro de las llaves un número-índice, que es la posición de las entradas en .format().
(4) En esta tercera forma sustituimos los valores directos por variables (lo que nos permite, por cierto. modificar interactivamente el contenido) y después empleamos las variables como contenido de .format(). las dos expresiones permiten comprobar que el uso de variables no modifica las propiedades y el modo de funcionar del procedimiento.
(5) Sobre la misma base de contenido que en 3, ahora en 4  expongo la forma más evolucionada del procedimiento: una clave identifica y se diferencia del valor o contenido que no es otro que el nombre de las variables. Esa clave es la que se escribe dentro de las llaves, en sustitución y como alternativa del valor-índice empleado en formas previas. La ventaja de esta fórmula es que se asocia al uso de diccionarios.
(6) f-string y format() son incompatibles, esto es: no se pueden usar en la misma concatenación. En el ejemplo anterior, tercera línea, tanto si eliminamos f como si añadimos format() para identificar la segunda variable o cualquier otra, se produce un funcionamiento anómalo.  Obsérvese en la cuarta línea cómo se utiliza f-string cuando iniciamos la cadena con una variable: necesitamos incluirla en una cadena literal, esto es: dentro de comillas (' '/" ") e identificada como tal variable entre llaves. Cualquier otra sintaxis provoca error o respuesta no deseada.


Lenguajes. Python.

Concatenar cadenas


Seguro que has echado de menos la posibilidad de crear textos con más contenido y de mayor complejidad. Una de las causas es la ausencia de instrucciones o procedimientos para encadenar contenidos textual. Sin esto recursos las limitaciones de cualquier lenguaje son muchas. En esta entrada vamos a aprender a concatenar cadenas, variables y cadenas con variables. En realidad todo es uno, así que sabiendo la diferencia entre una cadena (cómo se expresa) y una variable que contiene una cadena (cosa que ya hemos visto) tenemos la mitad del trabajo hecho.


Antes de entrar en materia, no está de más que expliquemos brevemente las razones por las que aprender a concatenar cadenas y variables es de tanta importancia para nuestro objetivo. Y la respuesta es muy simple: sin concatenar nos vemos limitados bien a la parquedad de los datos que podemos procesar (con lo que difícilmente podremos hablar de trabajo con texto) o a la literalidad de la información que mostremos por pantalla (lo que compromete la posibilidad real de automatizar la creación de textos). Por el contrario, concatenando cadenas estamos iniciando el camino hacia la creación de textos, aunque sólo iniciándolo, como podremos comprobar más adelante.

Cuando escribimos un texto con nuestro procesador estamos concatenando contenidos, ya que casi la propia definición de este tipo de dato supone la acción de concatenar; pero cuando más evidente es la necesidad de concatenar cadenas es cuando necesitamos ajustar ciertas partes de su contenido a condiciones específicas, como son las derivadas de la concordancia de género y número, los tiempos verbales o las implicaciones derivadas de ciertas condiciones asociadas a otros contenidos. Aunque suene enrevesado (y lo es en su complejidad gramatical y semántico-contextual), en realidad es algo que realizamos de forma automatizada que no nos damos cuenta, puesto que es el resultado de nuestra competencia lingüística y lógico-discursiva.

Pero lo que es simple para nosotros puede resultar una gran dificultad para un programa informático, y la prueba la tenemos en los complejos algoritmos que emplea la IA para identificar la palabra que corresponda suceder a otras previas en una frase simple. 

Pero tranquilo, que por ahora no nos vamos a preocupar por este tipo de cuestiones. La concatenación sirve para cosas mucho más simples pero de gran importancia como crear mensajes personalizados y/o unir string y/o variables tipo string para generar contenido textual de mayor complejidad. Y por ahora es a lo que nos vamos a limitar, que no es poco.

La primer forma que podemos usar para concatenar string (y string con variables) es utilizar el operador +. Un ejemplo:

a = "Hola"
b = "Mundo"

a+b = HolaMundo

Puedes observar que el resultado presenta un "pequeño" problema": los dos string aparecen unidos sin separación entre ellos. Si queremos evitarlo deberemos añadir un espacio al final del contenido de la primera (a = "Hola ") para obtener lo que esperamos (a+b = "Hola Mundo") y problema resuelto.

Una segunda forma de concatenar string, más adaptada a este tipo de dato es usar la coma como referente para la concatenación, pero presenta algunos problemas de manejo:

a= input()
Hola
b = input()
Mundo
c = a,b
print(c)
('Hola', 'Mundo')

Como puedes ver, de esta forma (c = a,b), más que concatenar lo que hacemos es identificar (y diferenciar) los componentes del string resultante (print(c) -> ('Hola', 'Mundo')), por lo que no nos resulta útil para nuestro objetivo. 

Sin embargo, si aplicamos la función print() directamente sobre las variables creadas (print(a,b)) obtenemos el resultado esperado (Hola Mundo). El mismo resultado que obtenemos si asignamos a c ambas cadenas, incluyendo un espacio entra ambas (c = a + " " +b -> print(c) -> Hola Mundo)

En consecuencia, la forma más sencilla de concatenar cadenas es hacerlo mediante el operador +, que al aplicarlo a string asume la función de unión de elementos. Sin embargo, Python dispone de formas más potentes y flexibles de concatenar cadenas. Veamos algunas de ellas (1).

Primero sobre el pyshell, que será la primera utilidad del IDLE que empleemos. El prompt [>>>] nos indica que pyshell está dispuesto para recibir instrucciones, a la vez que permite diferenciar éstas del resultado de su ejecución: fíjate que las dos primeras líneas de código van precedidas de >>>, pero la tercera (la respuesta o salida/output) no. Esta es una peculiaridad del Shell que no presentan otros soporte de escritura del código.

Después sobre el código mismo:

  • La primera línea del programa, ya sabes, sirve para declarar+asignar contenido a la variable (varNombre="Javier")
  • Al hacerlo con una cadena de texto, implícitamente asignamos a la variable al tipo String. 
  • Un número entrecomillado también se considera un String, pero no si no va entrecomillado.
  • La segunda línea sirve para ordenar la escritura en pantalla del contenido de la variable mediante la instrucción print(). Ésta es la única forma válida de escribirla y cualquier diferencia se considera un error.
  • Tenemos que tener mucho cuidado al escribir el nombre de la variable que contiene print() entre sus paréntesis, ya que también en esto Python es muy estricto: varNombre no es VarNombre, ni Varnombre, ni var_nombre, ni cualquiera otra variación, igualmente válidas como nombres de variables, pero diferentes, por lo que el intérprete Python las identificará como inexistentes.
  • Aquí pasamos a print() una variable, pero también es posible pasarle un carácter, una palabra o una cadena de texto (o un número con función nominal o de categoría). En este caso, al igual que en la asignación del dato a la variable, debemos usar "" o ''.

Para concatenar variables alfanuméricas, en Python podemos emplear dos operadores: (,) y (+)

Para

var1 = "Hola"
var2 = "Mundo"

Con (,):

print(var1,var2) 
 
Obtenemos Hola Mundo. Observa que entre las dos variables intercala un espacio en blanco.

Y con (+):

print(var1+var2)

Obtenemos HolaMundo, que es el resultado esperado de una concatenación de variables string.

Para intercalar un espacio en blanco debemos incluirlo directamente o mediante una tercera variable cuyo dato sea una cadena vacía.

 print(var1+" "+var2)

Nos da como salida (output)  Hola Mundo

Python  permite realizar otras muchas manipulaciones de las cadenas, que iremos viendo en su momento, pero quiero mostrarte algo que creo resulta de interés para entender cómo maneja python las cadenas:

print(var1[1]) devuelve o
print(var1[0]) devuelve H
 
Como puedes ver, Python genera un índice de elementos (caracteres) de la cadena, pudiendo acceder a cada uno de sus componentes mediante su índice.
 
El primer elemento de ese índice es 0, por eso la segunda línea devuelve el carácter H.
En otros lenguajes (OOo Basic, por ejemplo) eso implica que la cadena es tratada como un array de caracteres.

Vamos a comprobar ahora qué sucede cuando usamos estos concatenadores con variables de diferente tipo.

Es necesario recordar una implicación de la declaración implícita de Python: al contrario que en OB, no es posible declarar una variable como string y atribuirle un valor numérico, por lo que necesariamente tenemos que entrecomillar el número si queremos que funciones como un carácter. En consecuencia...

var1 = "2"
var2 = "3"
print(var1+var2)

... si concatenamos var1 con var2 obtendremos necesariamente 23

Pero si...

var1 = "2"
var2 = 3
print(var1+var2)

... el resultado no será el mismo, como sí sucede en OB, sino un mensaje de error

Traceback (most recent call last):
  File "<pyshell#14>", line 1, in <module>
    print(var1+var3)
TypeError: can only concatenate str (not "int") to str

En esto, Python se muestra mucho más riguroso en el tratamiento de los tipos de variables, lo que resulta conveniente para evitar errores en el procesamiento de los datos.

Para finalizar esta entrada, vamos a reproducir a continuación ese primer script que ya realizamos en PSeInt y en OOo Basic. Me interesa para analizar el modo en que Python plantea la posibilidad de interactuar con el usuario en la forma más básica.

var1=input("Dame un número ")
Dame un número 24
var2=input("Dame otro número ")
Dame otro número 24
print(var1+var2)

    Salida -> 2424

El resultado es la concatenación de dos variables string, no la suma de dos cantidades, lo que contrasta con el resultado que obtendríamos si hubiéramos realizado el input directamente desde el código (sin emplear la instrucción input().

Para obtener el resultado esperado (24+24 = 48) deberemos convertir las variables alfanuméricas a numéricas, haciendo uso de funciones específicas de conversión, algo de lo que aun no hemos hablado, pero que está presente en todos los lenguajes de programación.

print(int(var1)+int(var2)) nos permite obtener el resultado esperado: 48


NOTAS

(1) Efectivamente un operador matemático, pero es que no es el único que podemos emplear con un string, también otros como el de multiplicar. En la lógica del lenguaje "ab"*2 es una expresión perfectamente valida("ab"*2 -> 'abab'), pero no así otras operaciones. Aparentemente esta operación carece de utilidad, pero puede serlo para crear series alfanuméricas, especialmente si combinamos la operación con el uso de colecciones de datos, como una lista.
(2) Dejaremos las de mayor complejidad para más adelante, cuando nos resulte más fácil entender su significado y funcionamiento.