Diferències
Ací es mostren les diferències entre la revisió seleccionada i la versió actual de la pàgina.
| Ambdós costats versió prèvia Revisió prèvia | |||
| info:cursos:netacad:python:pe2m2:cadenas [30/06/2022 11:02] – mate | info:cursos:netacad:python:pe2m2:cadenas [30/06/2022 12:08] (actual) – mate | ||
|---|---|---|---|
| Línia 1123: | Línia 1123: | ||
| * **startswith()**: | * **startswith()**: | ||
| + | == Comparando cadenas | ||
| + | Las cadenas en Python pueden ser comparadas usando el mismo conjunto de operadores que se emplean con los números. | ||
| + | Observa estos operadores: también sirven para comparar cadenas: | ||
| + | * == | ||
| + | * != | ||
| + | * > | ||
| + | * >= | ||
| + | * < | ||
| + | * <= | ||
| + | Existe un " | ||
| + | Los resultados que se obtienen de una operación de este tipo a veces son sorprendentes. Comencemos con los casos más simples. | ||
| + | Dos cadenas son iguales cuando consisten de los mismos caracteres en el mismo orden. Del mismo modo, dos cadenas no son iguales cuando no consisten de los mismos caracteres en el mismo orden. | ||
| + | Ambas comparaciones dan True (verdadero) como resultado: | ||
| + | < | ||
| + | ' | ||
| + | ' | ||
| + | </ | ||
| + | La relación entre cadenas se determina al **comparar el primer carácter diferente en ambas cadenas** (ten en cuenta los puntos de código ASCII / UNICODE en todo momento). | ||
| + | Cuando se comparan dos cadenas de diferentes longitudes y la más corta es idéntica a la más larga, la **cadena más larga se considera mayor**. | ||
| + | Justo como aquí: | ||
| + | < | ||
| + | ' | ||
| + | </ | ||
| + | La comparación es True (verdadera). | ||
| + | La comparación de cadenas siempre distingue entre mayúsculas y minúsculas (**las letras mayúsculas se consideran menores en comparación con las minúsculas**). | ||
| + | La expresión es True (verdadera): | ||
| + | < | ||
| + | ' | ||
| + | </ | ||
| + | Aún **si una cadena contiene solo dígitos, todavía no es un número**. Se interpreta como lo que es, como cualquier otra cadena regular, y su aspecto numérico (potencial) no se toma en cuenta, en ninguna manera. | ||
| + | Observa los ejemplos: | ||
| + | < | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | </ | ||
| + | Producen los siguientes resultados: | ||
| + | < | ||
| + | False | ||
| + | True | ||
| + | False | ||
| + | True | ||
| + | True | ||
| + | </ | ||
| + | **El comparar cadenas con los números generalmente es una mala idea**. | ||
| + | Las únicas comparaciones que puede realizar con impunidad son aquellas simbolizadas por los operadores **==** y **!=**. El primero siempre devuelve False (falso), mientras que el segundo siempre devuelve True (verdadero). | ||
| + | El uso de cualquiera de los operadores de comparación restantes generará una excepción TypeError. | ||
| + | Vamos a verlo: | ||
| + | < | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | </ | ||
| + | |||
| + | Los resultados en este caso son: | ||
| + | < | ||
| + | False | ||
| + | True | ||
| + | False | ||
| + | True | ||
| + | TypeError exception | ||
| + | </ | ||
| + | |||
| + | == Ordenamiento | ||
| + | La comparación está estrechamente relacionada con el ordenamiento (o más bien, el ordenamiento es, de hecho, un caso muy sofisticado de comparación). | ||
| + | |||
| + | Esta es una buena oportunidad para mostrar dos formas posibles de **ordenar listas que contienen cadenas**. Dicha operación es muy común en el mundo real: cada vez que ves una lista de nombres, productos, títulos o ciudades, esperas que este ordenada. | ||
| + | |||
| + | Supongamos que deseas ordenar la siguiente lista: | ||
| + | < | ||
| + | greek = [' | ||
| + | </ | ||
| + | |||
| + | En general, Python ofrece dos formas diferentes de ordenar las listas. | ||
| + | |||
| + | El primero se implementa con una función llamada **sorted()**. | ||
| + | |||
| + | La función toma un argumento (una lista) y **retorna una nueva lista**, con los elementos ordenados del argumento. (Nota: esta descripción está un poco simplificada en comparación con la implementación real; lo discutiremos más adelante). | ||
| + | |||
| + | La lista original permanece intacta. | ||
| + | |||
| + | <code python># Demostración de la función sorted(): | ||
| + | first_greek = [' | ||
| + | first_greek_2 = sorted(first_greek) | ||
| + | |||
| + | print(first_greek) | ||
| + | print(first_greek_2) | ||
| + | |||
| + | print()</ | ||
| + | El código produce el siguiente resultado: | ||
| + | < | ||
| + | [' | ||
| + | [' | ||
| + | </ | ||
| + | |||
| + | El segundo método afecta a la lista misma - **no se crea una nueva lista**. El ordenamiento se realiza por el método denominado **sort()**. | ||
| + | |||
| + | <code python># Demostración del método sort(): | ||
| + | second_greek = [' | ||
| + | print(second_greek) | ||
| + | |||
| + | second_greek.sort() | ||
| + | print(second_greek)</ | ||
| + | |||
| + | La salida no ha cambiado: | ||
| + | < | ||
| + | [' | ||
| + | [' | ||
| + | </ | ||
| + | |||
| + | Si necesitas un ordenamiento diferente, debes convencer a la función o método de cambiar su comportamiento predeterminado. Lo discutiremos pronto. | ||
| + | |||
| + | == Cadenas frente a números | ||
| + | Hay dos cuestiones adicionales que deberían discutirse aquí: **¿Cómo convertir un número (un entero o un flotante) en una cadena, y viceversa? | ||
| + | |||
| + | La conversión de cadena a número es simple, ya que siempre es posible. Se realiza mediante una función llamada **str()**. | ||
| + | |||
| + | Justo como aquí: | ||
| + | <code python> | ||
| + | itg = 13 | ||
| + | flt = 1.3 | ||
| + | si = str(itg) | ||
| + | sf = str(flt) | ||
| + | |||
| + | print(si + ' ' + sf) | ||
| + | </ | ||
| + | |||
| + | La salida del código es: | ||
| + | < | ||
| + | 13 1.3 | ||
| + | </ | ||
| + | |||
| + | La transformación inversa solo es posible cuando la cadena representa un número válido. Si no se cumple la condición, espera una excepción ValueError. | ||
| + | |||
| + | Emplea la función **int()** si deseas obtener un entero, y **float()** si necesitas un valor punto flotante. | ||
| + | |||
| + | Justo como aquí: | ||
| + | <code python> | ||
| + | si = ' | ||
| + | sf = ' | ||
| + | itg = int(si) | ||
| + | flt = float(sf) | ||
| + | |||
| + | print(itg + flt) | ||
| + | </ | ||
| + | |||
| + | Esto es lo que verás en la consola: | ||
| + | < | ||
| + | 14.3 | ||
| + | </ | ||
| + | |||
| + | == Puntos Claves | ||
| + | 1. Las cadenas se pueden comparar con otras cadenas utilizando operadores de comparación generales, pero compararlas con números no da un resultado razonable, porque **ninguna cadena puede ser igual a ningún otro número**. Por ejemplo: | ||
| + | |||
| + | * cadena == número es siempre False (falso). | ||
| + | * cadena != número es siempre True (verdadero). | ||
| + | * cadena >= número siempre **genera una excepción**. | ||
| + | |||
| + | 2. El ordenamiento de listas de cadenas se puede realizar mediante: | ||
| + | |||
| + | Una función llamada **sorted()**, | ||
| + | Un método llamado **sort()**, el cual ordena la lista en el momento. | ||
| + | |||
| + | 3. Un número se puede convertir en una cadena empleando la función **str()**. | ||
| + | |||
| + | 4. Una cadena se puede convertir en un número (aunque no todas las cadenas) empleando ya sea la función **int()** o **float()**. La conversión falla si la cadena no contiene un número válido (se genera una excepción en dicho caso). | ||
| + | |||
| + | === ejemplo: El Cifrado César: encriptando un mensaje | ||
| + | Te mostraremos cuatro programas simples para presentar algunos aspectos del procesamiento de cadenas en Python. Son intencionalmente simples, pero los problemas de laboratorio serán significativamente más complicados. | ||
| + | |||
| + | El primer problema que queremos mostrarte se llama Cifrado César - más detalles aquí: https:// | ||
| + | |||
| + | Este cifrado fue (probablemente) inventado y utilizado por Cayo Julio César y sus tropas durante las Guerras Galas. La idea es bastante simple: cada letra del mensaje se reemplaza por su consecuente más cercano (A se convierte en B, B se convierte en C, y así sucesivamente). La única excepción es la Z, la cual se convierte en A. | ||
| + | |||
| + | El programa en el editor es una implementación muy simple (pero funcional) del algoritmo. | ||
| + | |||
| + | <sxh python> | ||
| + | # Cifrado César. | ||
| + | text = input(" | ||
| + | cipher = "" | ||
| + | for char in text: | ||
| + | if not char.isalpha(): | ||
| + | continue | ||
| + | char = char.upper() | ||
| + | code = ord(char) + 1 | ||
| + | if code > ord(' | ||
| + | code = ord(' | ||
| + | cipher += chr(code) | ||
| + | |||
| + | print(cipher) | ||
| + | </ | ||
| + | |||
| + | Se ha escrito utilizando los siguientes supuestos: | ||
| + | |||
| + | * Solo acepta letras latinas (nota: los Romanos no usaban espacios en blanco ni dígitos). | ||
| + | * Todas las letras del mensaje están en mayúsculas (nota: los Romanos solo conocían las mayúsculas). | ||
| + | Veamos el código: | ||
| + | |||
| + | * La línea 02: pide al usuario que ingrese un mensaje (sin cifrar) de una línea. | ||
| + | * La línea 03: prepara una cadena para el mensaje cifrado (esta vacía por ahora). | ||
| + | * La línea 04: inicia la iteración a través del mensaje. | ||
| + | * La línea 05: si el carácter actual no es alfabético... | ||
| + | * La línea 06: ...ignoralo. | ||
| + | * La línea 07: convierta la letra a mayúsculas (es preferible hacerlo a ciegas, en lugar de verificar si es necesario o no). | ||
| + | * La línea 08: obtén el código de la letra e increméntalo en uno. | ||
| + | * La línea 09: si el código resultante ha " | ||
| + | * La línea 10: ... cámbialo al código de la A. | ||
| + | * La línea 11: agrega el carácter recibido al final del mensaje cifrado. | ||
| + | * La línea 13: imprime el cifrado. | ||
| + | El código, con este mensaje: | ||
| + | < | ||
| + | AVE CAESAR | ||
| + | </ | ||
| + | Da como salida: | ||
| + | < | ||
| + | BWFDBFTBS | ||
| + | </ | ||
| + | |||
| + | == ejemplo: El Cifrado César: descifrando un mensaje | ||
| + | La operación inversa ahora debería ser clara para ti: solo presentamos el código tal como está, sin ninguna explicación. | ||
| + | |||
| + | Observa el código en el editor. Comprueba cuidadosamente si funciona. Usa el criptograma del programa anterior. | ||
| + | |||
| + | <sxh python> | ||
| + | # Cifrado César - descifrar un mensaje. | ||
| + | cipher = input(' | ||
| + | text = "" | ||
| + | for char in cipher: | ||
| + | if not char.isalpha(): | ||
| + | continue | ||
| + | char = char.upper() | ||
| + | code = ord(char) - 1 | ||
| + | if code < ord(' | ||
| + | code = ord(' | ||
| + | text += chr(code) | ||
| + | |||
| + | print(text) | ||
| + | </ | ||
| + | |||
| + | == ejemplo: El Procesador de Números | ||
| + | El tercer programa muestra un método simple que permite ingresar una línea llena de números y sumarlos fácilmente. Nota: la función input(), combinada junto con las funciones int() o float(), no es lo adecuado para este propósito. | ||
| + | |||
| + | El procesamiento será extremadamente fácil: queremos que se sumen los números. | ||
| + | |||
| + | Observa el código en el editor. Analicémoslo. | ||
| + | |||
| + | Emplear listas puede hacer que el código sea más pequeño. Puedes hacerlo si quieres. | ||
| + | |||
| + | Presentemos nuestra versión: | ||
| + | |||
| + | <sxh python> | ||
| + | #Procesador de Números. | ||
| + | |||
| + | line = input(" | ||
| + | strings = line.split() | ||
| + | total = 0 | ||
| + | try: | ||
| + | for substr in strings: | ||
| + | total += float(substr) | ||
| + | print(" | ||
| + | except: | ||
| + | print(substr, | ||
| + | |||
| + | </ | ||
| + | |||
| + | * La línea 03: pide al usuario que ingrese una línea llena de cualquier cantidad de números (los números pueden ser flotantes). | ||
| + | * La línea 04: divide la línea en una lista con subcadenas. | ||
| + | * La línea 05: se inicializa la suma total a cero. | ||
| + | * La línea 06: como la conversión de cadena a flotante puede generar una excepción, es mejor continuar con la protección del bloque try-except. | ||
| + | * La línea 07: itera a través de la lista... | ||
| + | * La línea 08: ... e intenta convertir todos sus elementos en números flotantes; si funciona, aumenta la suma. | ||
| + | * La línea 09: todo está bien hasta ahora, así que imprime la suma. | ||
| + | * La línea 10: el programa termina aquí en caso de error. | ||
| + | * La línea 11: imprime un mensaje de diagnóstico que muestra al usuario el motivo de la falla. | ||
| + | El código tiene una debilidad importante: muestra un resultado falso cuando el usuario ingresa una línea vacía. ¿Puedes arreglarlo? | ||
| + | |||
| + | == ejemplo: El Validador IBAN | ||
| + | El cuarto programa implementa (en una forma ligeramente simplificada) un algoritmo utilizado por los bancos Europeos para especificar los números de cuenta. El estándar llamado IBAN (Número de cuenta bancaria internacional) proporciona un método simple y bastante confiable para validar los números de cuenta contra errores tipográficos simples que pueden ocurrir durante la reescritura del número, por ejemplo, de documentos en papel, como facturas o facturas en las computadoras. | ||
| + | |||
| + | Puedes encontrar más detalles aquí: https:// | ||
| + | |||
| + | Un número de cuenta compatible con IBAN consta de: | ||
| + | |||
| + | * Un código de país de dos letras tomado del estándar ISO 3166-1 (por ejemplo, FR para Francia, GB para Gran Bretaña DE para Alemania, y así sucesivamente). | ||
| + | * Dos dígitos de verificación utilizados para realizar las verificaciones de validez: pruebas rápidas y simples, pero no totalmente confiables, que muestran si un número es inválido (distorsionado por un error tipográfico) o válido. | ||
| + | * El número de cuenta real (hasta 30 caracteres alfanuméricos; | ||
| + | El estándar dice que la validación requiere los siguientes pasos (según Wikipedia): | ||
| + | |||
| + | * (Paso 1) Verificar que la longitud total del IBAN sea correcta según el país (este programa no lo hará, pero puedes modificar el código para cumplir con este requisito si lo deseas; nota: pero debes enseñar al código a conocer todas las longitudes utilizadas en Europa). | ||
| + | * (Paso 2) Mueve los cuatro caracteres iniciales al final de la cadena (es decir, el código del país y los dígitos de verificación). | ||
| + | * (Paso 3) Reemplaza cada letra en la cadena con dos dígitos, expandiendo así la cadena, donde A = 10, B = 11 ... Z = 35. | ||
| + | * (Paso 4) Interpreta la cadena como un entero decimal y calcula el residuo de ese número dividiéndolo entre 97. Si el residuo es 1, pasa la prueba de verificación de dígitos y el IBAN puede ser válido. | ||
| + | |||
| + | <sxh python> | ||
| + | # Validador IBAN. | ||
| + | |||
| + | iban = input(" | ||
| + | iban = iban.replace(' | ||
| + | |||
| + | if not iban.isalnum(): | ||
| + | print(" | ||
| + | elif len(iban) < 15: | ||
| + | print(" | ||
| + | elif len(iban) > 31: | ||
| + | print(" | ||
| + | else: | ||
| + | iban = (iban[4:] + iban[0: | ||
| + | iban2 = '' | ||
| + | for ch in iban: | ||
| + | if ch.isdigit(): | ||
| + | iban2 += ch | ||
| + | else: | ||
| + | iban2 += str(10 + ord(ch) - ord(' | ||
| + | iban = int(iban2) | ||
| + | if iban % 97 == 1: | ||
| + | print(" | ||
| + | else: | ||
| + | print(" | ||
| + | </ | ||
| + | |||
| + | * Línea 03: pide al usuario que ingrese el IBAN (el número puede contener espacios, ya que mejoran significativamente la legibilidad del número... | ||
| + | * Línea 04: ... pero remueve los espacios de inmediato). | ||
| + | * Línea 05: el IBAN ingresado debe constar solo de dígitos y letras, de lo contrario... | ||
| + | * Línea 06: ... muestra un mensaje. | ||
| + | * Línea 07: el IBAN no debe tener menos de 15 caracteres (esta es la variante más corta, utilizada en Noruega). | ||
| + | * Línea 08: si es más corto, se informa al usuario. | ||
| + | * Línea 09: además, el IBAN no puede tener más de 31 caracteres (esta es la variante más larga, utilizada en Malta). | ||
| + | * Línea 10: si es más largo, se le informa al usuario. | ||
| + | * Línea 11: se comienza con el procesamiento. | ||
| + | * Línea 12: se mueven los cuatro caracteres iniciales al final del número y se convierten todas las letras a mayúsculas (paso 02 del algoritmo). | ||
| + | * Línea 13: esta es la variable utilizada para completar el número, creada al reemplazar las letras con dígitos (de acuerdo con el paso 03 del algoritmo). | ||
| + | * Línea 14: iterar a través del IBAN. | ||
| + | * Línea 15: si el carácter es un dígito... | ||
| + | * Línea 16: ... se copia. | ||
| + | * Línea 17: de lo contrario... | ||
| + | * Línea 18: ... conviértelo en dos dígitos (observa cómo se hace aquí). | ||
| + | * Línea 19: la forma convertida del IBAN está lista: ahora se convierte en un número entero. | ||
| + | * Línea 20: ¿el residuo de la división de iban2 entre 97 es igual a 1? | ||
| + | * Línea 21: si es así, entonces el número es correcto. | ||
| + | * Línea 22: de lo contrario... | ||
| + | * Línea 23: ... el número no es válido. | ||
| + | * | ||
| + | Agreguemos algunos datos de prueba (todos estos números son válidos; puedes invalidarlos cambiando cualquier carácter). | ||
| + | < | ||
| + | Inglés: GB72 HBZU 7006 7212 1253 00 | ||
| + | Francés: FR76 30003 03620 00020216907 50 | ||
| + | Alemán: DE02100100100152517108 | ||
| + | </ | ||
| + | |||
| + | == Puntos Claves | ||
| + | 1. Las cadenas son herramientas clave en el procesamiento de datos modernos, ya que la mayoría de los datos útiles son en realidad cadenas. Por ejemplo, el uso de un motor de búsqueda web (que parece bastante trivial en estos días) utiliza un procesamiento de cadenas extremadamente complejo, que involucra cantidades inimaginables de datos. | ||
| + | |||
| + | 2. El comparar cadenas de forma estricta (como lo hace Python) puede ser muy insatisfactorio cuando se trata de búsquedas avanzadas (por ejemplo, durante consultas extensas a bases de datos). En respuesta a esta demanda, se han creado e implementado una serie de algoritmos de comparación de cadenas difusos. Estos algoritmos pueden encontrar cadenas que no son iguales en el sentido de Python, pero que son **similares**. | ||
| + | |||
| + | Uno de esos conceptos es la **Distancia Hamming**, que se utiliza para determinar la similitud de dos cadenas. Si este tema te interesa, puedes encontrar más información al respecto aquí: https:// | ||
| + | |||
| + | 3. Otra forma de comparar cadenas es encontrar su similitud acústica, lo que significa un proceso que lleva a determinar si dos cadenas suenan similares (como " | ||
| + | |||
| + | Un algoritmo utilizado para realizar una comparación de este tipo para el idioma Inglés se llama **Soundex** y se inventó, no lo creerás, en 1918. Puedes encontrar más información al respecto aquí: https:// | ||
| + | |||
| + | 4. Debido a la precisión limitada de los datos enteros y flotantes nativos, a veces es razonable almacenar y procesar valores numéricos enormes como cadenas. Esta es la técnica que usa Python cuando se le fuerza a operar con un número entero que consta de una gran cantidad de dígitos. | ||