Python para Ciencias de la Tierra

Capítulo 2: Conceptos Básicos de Programación en Python (Pt. 2)

Damian
15 min readMar 9, 2022

--

Índice del curso
<<
Capítulo 2: Conceptos Básicos de Programación (Pt. 1)

2.2 Estructuras Básicas de Datos

Las estructuras de datos son formas de representar y organizar datos en un equipo informático, los cuales suelen llamarse elementos. Permiten guardar datos de diferentes tipos para de forma efectiva poder acceder a ellos, modificarlos u operar con ellos. A no ser que se indique lo contrario, a los datos guardados en una estructura se les puede llamar elementos o registros, pero formalmente se procura evitar este último porque existe una estructura llamada registro.

Existen diversas estructuras de datos, algunas de ellas son objetos propios de python, pero existen muchas más que de acuerdo a su definición se pueden programar. Todas están diseñadas para diversas aplicaciones, sin embargo tienen en común operaciones, como el apilado de datos, la consulta de un elemento o la eliminación de elementos.

Las estructuras propias de python más utilizadas que veremos a continuación son las cadenas, las listas, las tuplas, los diccionarios y los conjuntos. Más adelante y cuando sea necesario, veremos otras estructuras.

Cadenas

Una cadena es tal vez la estructura de datos más simple, la cual es una secuencia de caracteres que se interpretan como un único tipo de dato, como vimos en la sesión anterior. Puede ser tan extensa como se desee, pero se debe recordar que todo lo que contenga, será considerado como carácter, sea letra, número o un símbolo.

Algo más que debes saber sobre las cadenas es que son inmutables, es decir, ningún elemento que contenga puede modificarse.

A partir de ahora puedes abrir un nuevo cuaderno en jupyter.

Puedes habilitar la primera celda como markdown, y escribir como título Cadenas. Haz esto con cada estructura que veamos.

Hemos visto que las cadenas se definen mediante el uso de comillas simples o dobles. ¿Cuáles usar? Las que tú quieras, pero debes saber que si en el texto de la cadena necesitas incluir comillas, las otras comillas deben definir a la cadena. Por ejemplo:

cadena = 'Pero siempre contestaban: "Es un sombrero".'

En este caso las comillas simples se utilizaron para definir el inicio y final de la cadena, pero era necesario usar comillas dentro de ella, por lo que las comillas dobles fueron útiles para evitar que python se confunda de dónde empieza y termina la variable. Si la definición de la cadena hubiera sido con comillas dobles, las comillas internas deben ser sencillas. Y así con todo el texto que desees utilizar como dato o impresión en pantalla.

Aclarado esto, ahora veremos cómo trabajar con cadenas.

Las cadenas son secuencias de elementos, donde cada elemento es un carácter que tiene índice asociado. El índice de un elemento dentro de varias estructuras de datos es la posición que ocupa, digamos, de izquierda a derecha. El índice te permite acceder a un carácter en particular utilizando corchetes contenedores de la posición, en el siguiente código, la posición 1:

verdura = 'zanahoria'
letra = verdura[1]
print(letra)

Si ejecutas estas líneas el resultado que verás es a, pero a no es la primera letra. ¿Por qué? Contrario a como las personas solemos contar, python cuenta a partir del 0, la segunda posición tiene el índice 1, la siguiente el 2, y así sucesivamente (figura 2.13). Se basa en el orden de los números enteros no negativos. Esta forma de enumerar la comparte con muchos otros lenguajes de programación.

letra = verdura[0]
print(letra)

Ahora sí obtendrás el resultado esperado: z.

Los números negativos también se pueden utilizar como índices. Pero el conteo es dicho de forma simple, regresivo. Es decir, el -1 es el último elemento, el -2 es el penúltimo, etcétera (figura 2.13).

Figura 2.13 Diagrama que muestra la distribución de índices positivos y negativos en una estructura. Como ejemplo, la palabra ‘zanahoria’.

Los índices además de dejarnos ver un elemento en particular, nos permiten extraer secciones o rebanadas de una cadena. Formalmente les llamamos subcadenas. La forma de extraerlas es con el uso de corchetes delimitando los índices inferior y superior:

c = 'Python es un intérprete'
rebanada = c[2:5]
print(rebanada)

El resultado es tho, donde la t tiene el índice 2, h tiene el índice 3, y o el 4. En las subcadenas no se incluye el segundo índice indicado, en este caso el índice 5, que es la n.

Cualquiera de los índices, sea el de la izquierda o el de la derecha, puede omitirse:

print(c[:6])
print(c[10:])

La primera subcadena impresa es ‘Python’, y la segunda es ‘un intérprete’. Por si te lo has preguntado, los espacios también cuentan con un índice, es decir, son un elemento. Si quieres probarlo, basta con que ejecutes el comando print(c[6]).

Aparentemente no hay respuesta, pero ten por seguro que ahí hay un espacio en blanco. Pero no confundir ese espacio con una cadena vacía. Ejecuta:

print(c[2:2])

Dicha línea ordena que se imprima el índice 2, pero al mismo tiempo lo omite por ser el segundo índice, generando otra vez un resultado en blanco, pero que ahora en realidad es un resultado vacío.

Podemos agregar un tercer índice dentro de los corchetes para obtener una rebanada discreta. La siguiente línea:

print(c[1:15:2])

>>yhne ni

El tercer índice indica un salto. En este caso le decimos a python que imprima cada segundo elemento, porque indicamos un 2 como tercer índice. De esta forma podemos generalizar la sintaxis del rebanado como cadena[inicio:final+1:salto].

Tamaño de una cadena
Más adelante veremos con detalle qué es una función, por ahora sólo ten en mente que son comandos que reciben uno o varios valores y parámetros de entrada, con el cual operan, para dar como resultado un valor de salida. Es un concepto similar a una función matemática. Su sintaxis es sencilla: función(parámetros)

Python tiene funciones incorporadas que básicamente nos facilitan la vida. Las hay de muchos tipos. Hay funciones que hacen una tarea ‘sencilla’, pero también hay las que hacen una tarea tan sofisticada que difícilmente un programador incluso experimentado, podría igualar o mejorar.

La función len nos permite conocer el tamaño de una cadena, es decir, el número de elementos que tiene. Para utilizarla basta con introducir en paréntesis la cadena de la que queremos saber su tamaño: len(cadena).

len(verdura)

Esta línea da como resultado 9, porque son nueve los caracteres que tiene la palabra zanahoria. Nota que la función len cambió al mismo color que print, lo cual indica que es una palabra que no debes usar para nombrar variables. Si deseas conocer el último elemento de la variable, puede que estés tentado a escribir algo así:

tamanio = len(verdura)         #se evita trabajar con ñ
print(verdura[tamanio])

El resultado será un error que detalla en qué línea está, qué clase de error es y una descripción de lo que lo ocasionó:

Figura 2.14: Error causado por introducir un índice fuera de rango.

El renglón al que ahora le prestamos atención es:

>> IndexError: string index out of range

El cual claramente nos dice que el índice que introducimos (recuerda que es 9) está fuera de rango. ¿Por qué? Porque los índices empiezan en cero, por lo que el número de elementos de una cadena siempre será una unidad más grande que su último índice, en este caso 8.

Así, la versión sin error de este pequeño código es:

tamanio = len(verdura)    
print(verdura[tamanio - 1])

Y tendrás como resultado la última letra de la palabra: a.

Como extra, puedes imprimir el tamaño de las subcadenas vistas arriba. Hago especial énfasis en las dos siguientes impresiones:

print(len(c[6]))    #Recuerda que era un espacio en blanco
print(len(c[2:2])) #Recuerda que era una cadena vacía

Los resultados son 1 y 0 respectivamente. Ahora tienes una herramienta para distinguir un espacio en blanco de una cadena vacía. Y aprovecho para que notes el uso de paréntesis. Así como en las operaciones matemáticas, siempre debemos cuidar que no se quede un paréntesis sin pareja. Por fortuna, y tal vez ya observaste, jupyter es tan amigable que básicamente siempre que abrimos algún signo de agrupación, en automático crea la pareja de signos.

Concatenación de Cadenas
Concatenar debe entenderse como la unión de dos cadenas, una al final de la otra. Es una forma de crear una nueva cadena a partir de la agregación de una o más a una cadena inicial, y la forma de hacerlo es con el símbolo de suma.

nombre = 'Laura'
apellido1 = 'González'
apellido2 = 'Rivera'
nombre_completo = nombre + ' ' + apellido1 + ' ' + apellido2
print(nombre_completo)

El resultado es ‘Laura González Rivera’. Observa que se agregaron espacios entre variables, porque éstos no eran parte de las variables. De haberlos omitido, el nombre hubiera salido todo junto (inténtalo).

Algunas Operaciones
No sólo la suma puede utilizarse en las cadenas, sino también la multiplicación. Así es, la multiplicación, pero sólo de una cadena por un número entero:

cadena = 'Palabra'
producto = cadena*3
print(producto)

>> PalabraPalabraPalabra

Vemos que se imprime tres veces la cadena, pero sin espacio. Para solucionarlo basta con que agregues un espacio a la variable cadena. Por ejemplo cadena = ‘Palabra ’, o concatenando el espacio en blanco.

Por si te lo preguntas, la resta y la división no están definidas entre cadenas.

Las cadenas se pueden comparar entre sí con los operadores que ya conocemos: >, ≥, =, ≤, <.

cadena >= nombre_completo

El resultado es True. ¿Pero qué es lo que se compara en realidad? No compara el tamaño de la cadena porque la segunda variable es más larga que la primera. Lo que compara es el orden que tienen las letras en el alfabeto. La variable cadena es mayor o igual que nombre_completo porque P por su posición en el alfabeto, es mayor que L.

Python distingue entre mayúsculas y minúsculas, y primero ordena las mayúsculas y después las minúsculas. Esto se puede ver si se le pregunta si a es mayor que Z. El resultado será True porque a a pesar de estar antes que la Z, al ser minúscula se le asigna un valor mayor (inténtalo).

El operador in nos permite saber si hay un carácter en la cadena, o no.

'a' in nombre

El resultado es True porque a sí está en la palabra Laura. Pero:

'j' in nombre

Da como resultado False.

Nota que in se colorea de verde, pero además toma un estilo de negrita. Esto es porque es un operador y no una función como len o print, y no requiere de un parámetro para funcionar, pero sí de una sintaxis. Más adelante verás otros operadores de este estilo.

Métodos de cadenas
Python es un lenguaje multiparadigma, es decir, admite distintas formas para programar un código. La más intuitiva y la que hemos trabajado es el paradigma imperativo, es decir, se declara instrucción por instrucción en el orden que queremos que las ejecute. Pero principalmente python ha sido pensado para ser tratado bajo el paradigma de la Programación Orientada a Objetos (POO u OOP por sus siglas en inglés). De hecho podemos decir que lo que se genera en python es un objeto en el sentido de la POO: las cadenas, los números, las listas, etcétera. La POO es un tema extenso que está fuera del alcance de este curso, pero comentaremos conceptos básicos para que la forma de trabajar de python se entienda con mayor claridad.

Un método es un concepto heredado de la POO. Se puede entender como una función, porque recibe parámetros y regresa resultados; propia de un objeto. Permite realizar alguna operación al dato que posee el objeto en cuestión, en este caso, una cadena. La sintaxis para utilizar un método difiere de la de una función, y es objeto.método(parámetros). En algunos métodos los parámetros son opcionales.

Método .upper(): Regresa la cadena con el texto en mayúscula.

#Recuerda usar paréntesis, aunque estén vacíos.
print(nombre_completo.upper())

>>LAURA GONZÁLEZ RIVERA

Método .lower(): Contrario al método upper(), convierte al texto de la cadena en minúsculas.

print(nombre_completo.lower())

>>laura gonzález rivera

Hasta este punto puedes preguntarte si nuestra variable original ha sido modificada. La respuesta es no. Si imprimes de nuevo nombre_completo notarás que sigue escrita como inicialmente fue declarada. Como se había comentado, las cadenas son inmutables. Si deseas trabajar con el resultado, debes guardarlo en una nueva variable, como en el siguiente ejemplo.

Método .title(): Regresa como resultado la cadena con las letras iniciales de cada palabra en mayúscula, como si se tratara de un título.

titulo = c.title()
print(titulo)

>>Python Es Un Intérprete

Método .capitalize(): Hace mayúscula sólo a la primera letra de la cadena.

print(verdura.capitalize())

>>Verdura

Método .find(): Busca la cadena que especifiquemos como parámetro, y nos indica el primer índice en el que se encuentra.

c.find('é')

>>16

c.find('es')    #Sólo dará el índice de e, por ser la primera letra.

>>7

Si la cadena a buscar se repite varias veces, sólo da el índice de la primera posición en la que encuentra a la cadena.

verdura.find('a')

>>1

Método .replace(): Permite buscar y reemplazar un carácter por otro.
Sintaxis: objeto.replace(‘cadena a reemplazar’, ‘cadena sustituta’)

print(c.replace('un','EL'))

>>Python es EL intérprete

Método .startswith(): Regresa un resultado booleano, de acuerdo a si una cadena empieza o no con una subcadena introducida como parámetro.

print(c.startswith('Python'))

>>True

print(nombre_completo.startswith('Antonio'))

>>False

Método .strip(): Elimina un mismo carácter que esté al inicio y final de una cadena. De forma predeterminada elimina espacios.

cadena = '    texto   '
print(cadena.strip())

>>texto

animal = 'oso'
print(animal.strip('o'))

>>s

Método .split(): Separa a la cadena con un separador especificado, y la convierte en una lista con los elementos separados. Omite al separador en la lista resultado.

print(c.split(' '))    #Aquí el separador es un espacio.

>>[‘Python’, ‘es’, ‘un’, ‘intérprete’]

Existen muchos otros métodos, los cuales en sesiones posteriores veremos y también sabremos cómo conocerlos todos. En esta lista de métodos hice énfasis en el punto previo a cada uno, pero a partir de ahora se debe dar por entendido que se debe respetar esa sintaxis al utilizar cualquier otro método.

Un pequeño anuncio: Puedes descargar el código hecho en cada una de las sesiones y los ejercicios resueltos, así como apoyarme a hacer más contenido como éste, suscribiéndote a mi patreon: https://www.patreon.com/ciencias_tierra.

Listas

Las listas son una secuencia de elementos separados por una coma. Son la estructura de datos más utilizada en python. Al ser de propósito general, pueden admitir cualquier tipo de dato: numéricos, cadenas de texto, otras listas. A los elementos también se les puede llamar por el término inglés item. Justo acabas de ver una lista en el último ejemplo de los métodos de las cadenas.

Los elementos que conforman a una lista están delimitados por corchetes []. Una lista con sus elementos se declara de la siguiente forma:

numeros = [10, 15, 20, 25, 30]
minerales = ['calcita', 'dolomita', 'cuarzo', 'halita', 'diamante']

print(numeros, minerales)

>>[10, 15, 20, 25, 30] [‘calcita’, ‘dolomita’, ‘cuarzo’, ‘halita’, ‘diamante’]

Hemos guardado dos nuevas variables de varios elementos. La impresión de una lista muestra las comillas indicando que ese elemento es una cadena.

Es común que utilicemos las listas para agrupar elementos por clases, como arriba donde se distingue una lista para minerales y otra para números enteros. Pero también se pueden combinar datos sin restricción alguna:

lista = [2, 'pizza', 99.90, ['Josué Carlos', 'Suárez', 'López']]
print(lista)

En esta lista se tiene el entero 2, la cadena ‘pizza’, el flotante 99.90; y otra lista de cadenas como último elemento. La lista interna tiene un índice asociado único, y se dice que es una lista anidada.

Comparten varias formas de operar con las cadenas: Los índices se enumeran a partir del 0. Funcionan igual los índices negativos. Se pueden rebanar de la misma forma para crear sublistas. Se puede acceder a un elemento mediante el índice. La función len también sirve para listas, en realidad para cualquier estructura de datos. También se pueden concatenar listas con el operador de suma, así como repetir varias veces una lista con la multiplicación por un escalar. El operador in es válido. (figura 2.15).

Figura 2.15 Algunas formas de trabajar con cadenas, son iguales con las listas.

Las listas a diferencia de las cadenas son mutables, es decir, sus elementos se pueden modificar. La forma más rápida de hacerlo es mediante el índice del elemento a cambiar.

numeros[2] = 5
print(numeros)

>>[10, 15, 5, 25, 30]

Ahora en lugar de 20, está el 5 en la misma posición.

Si hay una lista anidada, para acceder a sus datos hay que utilizar doble corchete. Por ejemplo, en la variable lista definida arriba, para acceder a la cadena ‘Suárez’ primero debemos indicar el índice donde está la lista, en este caso 3. Luego el índice donde está el elemento dentro de esta lista interna:

print(lista[3][1])

>>Suárez

La modificación de un elemento propio de una lista anidada se hace bajo el mismo principio.

Por otro lado, se puede declarar una lista vacía de dos formas diferentes:

#Indicando sólo los corchetes
lista_1 = []
#utilizando la función list
lista_2 = list()

Personalmente recomiendo utilizar la función list, porque ante un vistazo rápido es claro de qué estructura se trata.

Métodos de listas

Método append(): Agrega un nuevo elemento al final de la lista.

#Puede agregarse a una lista con elementos
numeros.append(35)
#Puede agregarse a una lista vacía
lista_1.append('fluorita')
lista_1.append('labradorita')

print(numeros, lista_1)

>>[10, 15, 20, 25, 30, 35] [‘fluorita’, ‘labradorita’]

Método extend(): Agrega una lista a otra. Es similar a la concatenación.

minerales.extend(lista_1)
print(minerales)

>>[‘calcita’, ‘dolomita’, ‘cuarzo’, ‘halita’, ‘diamante’, ‘fluorita’, ‘labradorita’]

Método insert(): Inserta un nuevo elemento en una posición especificada: lista.insert(indice, elemento)

minerales.insert(3, 'pirita')

>> [‘calcita’, ‘dolomita’, ‘cuarzo’, ‘pirita’, ‘halita’, ‘diamante’, ‘fluorita’, ‘labradorita’]

El mineral ‘pirita’ se ha agregado en el índice 3.

Método sort(): Ordena los elementos de una lista de forma ascendente: del mínimo al máximo o alfabéticamente, de acuerdo a los criterios de comparación de las cadenas que hemos visto. Advertencia: Modifica la lista, por lo que debes cuidar si deseas o no trabajar con la lista ordenada de forma definitiva.

minerales.sort()
print(minerales)

>>[‘calcita’, ‘cuarzo’, ‘diamante’, ‘dolomita’, ‘fluorita’, ‘halita’, ‘labradorita’, ‘pirita’]

Si se desea ordenar la lista en forma descendente, en el método se debe especificar el parámetro reverse=True. Otra forma es con el método reverse().

Método index(): Regresa el índice de la primera ocurrencia del elemento que se escribe como parámetro.

print(minerales.index('diamante'))

>> 2

Método count(): Cuenta el número de veces que un elemento está dentro de la lista.

print(minerales.count('cuarzo'))

>> 1

Método pop(): Elimina el último elemento de la lista. Si conoces el índice del elemento a eliminar, puedes introducirlo como parámetro. A diferencia de los métodos vistos hasta ahora de las listas, éste regresa el valor eliminado, por si sólo se quiere sacar de la lista y guardar en otra variable.

minerales.pop()
mineral = minerales.pop(2)
print(minerales, mineral)

>> [‘calcita’, ‘cuarzo’, ‘dolomita’, ‘fluorita’, ‘halita’, ‘labradorita’] diamante

Método remove(): Elimina el elemento que se le indique como parámetro. Esto es por si desconoces el índice de dicho elemento. A diferencia de pop, no regresa valor para poder guardar.

numeros.remove(15)
print(numeros)

>>[10, 5, 25, 30, 35]

Si el elemento se repite en la lista, elimina sólo el primero con el que se encuentra.

Puedes eliminar varios elementos de una lista con el operador del y la definición de una sublista. Nota el espacio entre el operador y la sublista.

letras = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
del letras[2:7]
print(letras)

>>[‘a’, ‘b’, ‘h’, ‘i’, ‘j’]

Se han eliminado desde la c (índice 2) hasta la g (índice 6). El operador del es muy útil para eliminar variables, y lo veremos en el siguiente capítulo.

Las listas cuentan con varias funciones que como len, permiten conocer información sobre ellas y sus elementos. Algunas de las más utilizadas son:

  • sum(lista): Obtiene la suma de los elementos, siempre que éstos sean numéricos.
  • min(lista): Obtiene el valor mínimo de los elementos. Si los elementos son cadenas, obtiene el mínimo bajo el criterio de comparación ya hablado sobre cadenas.
  • max(lista): Obtiene el valor máximo de los elementos.
  • sorted(lista): Ordena los elementos de la lista, pero a excepto del método sort, no modifica a la lista original.

Tuplas

Las tuplas al igual que las listas admiten cualquier tipo de dato, pero tienen la gran diferencia en que son inmutables. Esto las hace útiles para guardar data que no desees cambiar, por ejemplo, coordenadas geográficas o mediciones tomadas en campo. Es más rápido acceder a los elementos en una tupla que en una lista. Están limitadas por paréntesis, aunque no es obligatorio para declarar una, se recomienda ampliamente siempre indicarlos. Así, podemos declararlas de dos formas distintas:

tupla_1 = 'a', 'b', 'c', 'd'
tupla_2 = ('a', 'b', 'c', 'd')

Ambas formas son correctas, y si las comparas python te dirá que ambas son iguales. Pero si imprimes una tupla, siempre se muestra entre paréntesis.

Si deseas crear una tupla con un solo elemento, debes marcar una coma al final del único elemento:

t_unico = ('a',)

De no hacerlo, python lo detectará como una cadena.

Una tupla vacía se declara con la función tuple:

tupla_vacia = tuple()

Pero por ser inmutable, tiene el detalle de no poderse rellenar con nuevos elementos.

Los índices en las tuplas tienen el mismo papel que en las listas. Pero sólo cuenta con los métodos count e index. Pueden verse más como un objeto para resguardar datos que para trabajar con ellos.

Ya puedes guardar tu cuaderno con el nombre sesion_3.

Recuerda visitar mi patreon: https://www.patreon.com/ciencias_tierra.

Hasta ahora hemos visto tres estructuras que son colecciones de datos ordenados, lo que permite manipularlos con índices. En la siguiente sesión veremos dos estructuras no ordenadas.

Ejercicios

2.7 - Preguntas de repaso. Trata de responderlas sin ejecutar una sola línea donde sea posible.*

a) Sea palabra = ‘constitución’, ¿cuál será el resultado si imprimes palabra[:]?

b) Sean a = ‘Bienvenidos’ y b = ‘al curso’, ¿qué se imprimirá al concatenar ambas cadenas con a + b, ‘Bienvenidos al curso’ o ‘Bienvenidosal curso’?

c) Menciona tres diferencias entre una lista y una tupla.

d) De la lista n_pares = [2,4,6,8,10,12,14,16], ¿qué resultado arroja n_pares[5]? ¿y n_pares[2:4]?

e) ¿Cuál es la diferencia entre una cadena y una lista en Python?

2.8 - Resuelve los siguientes ejercicios cortos. Procura hacer cada uno de los siguientes ejercicios en una celda de jupyter.**

a) Sean los números 20 y 32, hacer el código que imprima en pantalla:

>> La suma de 20 y 32 es 52

b) Sea la cadena “Geología Estructural”, escribir el código que imprima el número de caracteres que tiene.

c) Ahora invierte la cadena “Geología Estructural”. Tip: Los saltos en las cadenas pueden ser negativos.

d) Dada la lista de números numeros = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], crea una nueva lista que contenga solo los números pares de la lista original.

--

--

Damian

Anything I want and is related to data. Learning to become a Data Professional.