Autor/a

Christian Badillo

Fecha de publicación

11 de agosto de 2024

Introducción

En esta lección, aprenderemos sobre funciones y estructuras de control en Python. Las funciones son bloques de código que se pueden reutilizar en diferentes partes de un programa, permitiendo que el código sea más modular y fácil de mantener. Las estructuras de control son bloques de código que permiten controlar el flujo de ejecución de un programa, como bucles y declaraciones condicionales. Son dos conceptos fundamentales en programación que nos permiten escribir código más eficiente y legible.

Tabulación en Python

Antes de proceder, hay que explicar la tabulación en Python. A diferencia de otros lenguajes de programación que utilizan llaves {} para delimitar bloques de código, Python utiliza la tabulación para indicar la estructura del código. Esto significa que los bloques de código se definen por la cantidad de espacios o tabulaciones al principio de una línea. Es importante mantener la consistencia en la tabulación para que el código funcione correctamente. Por ejemplo, en una función, el cuerpo de la función debe estar tabulado con 4 espacios o una tabulación.

def funcion():
    # Cuerpo de la función
    print('Hola, mundo!')

Si no se mantiene la consistencia en la tabulación, Python generará un error de indentación. Por ejemplo, si el cuerpo de la función no está tabulado correctamente, se generará un error de sintaxis.

Funciones

Las funciones son bloques de código que se pueden reutilizar en diferentes partes de un programa, permitiendo que el código sea más modular y fácil de mantener. En Python, las funciones se definen con la palabra clave def, seguida del nombre de la función y una lista de parámetros entre paréntesis. El cuerpo de la función se define con una tabulación (4 espacios) y puede contener cualquier número de instrucciones.

Primero elaboremos una función sencilla, la cual se llamará saludo y recibirá un parámetro nombre:

Código
def saludo(nombre):
    print(f'Hola, {nombre}!')

saludo('Christian')
Hola, Christian!

En nuestra función usamos una f-string para imprimir un saludo personalizado, las f-strings son una forma de formatear cadenas de texto en Python, permitiendo la interpolación de variables dentro de una cadena. Para definir una f-string, se coloca una f antes de las comillas de apertura y se encierra la variable entre llaves {}. Es decir, le estamos diciendo a Python que reemplace {nombre} con el valor de la variable nombre que en este caso es 'Christian'.

Las funciones pueden devolver un valor usando la palabra clave return. Por ejemplo, la siguiente función cuadrado recibe un número x y devuelve su cuadrado:

Código
def cuadrado(x):
    return x ** 2

print(cuadrado(5))
25

Como habrás notado en los ejemplos anteriores, hemos usado el nombre de la función seguido de paréntesis para llamarla. En el caso de la función saludo, hemos pasado un argumento nombre entre los paréntesis. En el caso de la función cuadrado, hemos pasado el número 5. Estos argumentos se llaman parámetros y son los valores que la función espera recibir para realizar su tarea.

Hay varias formas de poner los argumentos en una función:

  • Argumentos posicionales: Los argumentos se pasan en el orden en que se definen en la función.
  • Argumentos con nombre: Los argumentos se pasan con el nombre del parámetro al que corresponden.
  • Argumentos por defecto: Los argumentos tienen un valor por defecto que se usa si no se proporciona un valor.
  • Argumentos variables: Los argumentos se pasan como una lista o un diccionario.

En los ejemplos hemos utilizado argumentos posicionales. A continuación, veremos cómo usar argumentos con nombre:

Código
def resta(num1, num2):
    return num1 - num2

print(resta(num1=10, num2=5))
5

En este caso, hemos pasado los argumentos num1 y num2 con sus nombres correspondientes y les hemos asignado valores. Esto nos permite pasar los argumentos en cualquier orden, siempre y cuando especifiquemos el nombre del parámetro al que corresponden.

Ahora veamos cómo usar argumentos por defecto:

Código
def potencia(base, exponente=2):
    return base ** exponente

print(potencia(2))
print(potencia(2, 3))
4
8

En este caso, la función potencia tiene un argumento exponente con un valor por defecto de 2. Si no se proporciona un valor para exponente, se usará el valor por defecto. Si se proporciona un valor, se usará ese valor en su lugar.

Funciones Lambda

Las funciones lambda son funciones anónimas que se pueden definir en una sola línea. Se definen con la palabra clave lambda, seguida de una lista de parámetros y una expresión que se evalúa y devuelve el resultado. Por ejemplo, la siguiente función lambda calcula el cuadrado de un número:

Código
cuadrado_lamda = lambda x: x ** 2

print(cuadrado_lamda(5))
25

Las funciones lambda son útiles cuando se necesita una función simple y no es necesario definirla con una declaración def.

Ahora definamos una función lambda un poco más compleja para sumar dos números:

Código
suma_lambda = lambda x, y: x + y

print(suma_lambda(3, 4))
7

Paquetes y Módulos

En Python, las funciones se pueden organizar en módulos y paquetes para facilitar la reutilización y la organización del código. Un módulo es un archivo que contiene definiciones y declaraciones de Python, como funciones, clases y variables. Un paquete es una colección de módulos organizados en un directorio. Es decir, que un paquete es una carpeta que contiene archivos de python (módulos) que contienen funciones, clases y variables que puedes utilizar en tu programa.

Hay paqueterias y modulos muy útiles que se pueden importar en Python, por ejemplo, la paquetería math que contiene funciones matemáticas comunes, como sqrt para calcular la raíz cuadrada de un número. Para importar un módulo o una función de un módulo, se utiliza la palabra clave import seguida del nombre del módulo.

import math

Una vez que se ha importado un módulo, se puede acceder a sus funciones y variables utilizando la notación de punto. Por ejemplo, para calcular la raíz cuadrada de un número, se puede utilizar la función sqrt del módulo math.

Código
import math
print(math.sqrt(16))
4.0

También es posible importar funciones específicas de un módulo utilizando la palabra clave from. Por ejemplo, para importar solo la función sqrt del módulo math, se puede hacer lo siguiente:

Código
from math import sqrt

print(sqrt(16))
4.0

Muchas veces las paqueterias tienen nombres muy largos, por lo que se pueden importar con un alias utilizando la palabra clave as, las paqueterias más comunes en python tienen alias ya acordados en la comunidad, por ejemplo, pandas una paquetería muy utilizada para el análisis de datos se importa con el alias pd.

import pandas as pd

De esta forma, se puede acceder a las funciones y variables de la paquetería pandas utilizando el alias pd.

Existe un gran número de paqueterías y módulos disponibles en Python que proporcionan funcionalidades adicionales para tareas específicas, como el análisis de datos, la visualización, el aprendizaje automático, etc. Estas paqueterías pueden ser muy útiles para acelerar el desarrollo de aplicaciones y realizar tareas complejas de manera eficiente.

No todas las paqueterias vienen preinstaladas con Python, por lo que es necesario instalarlas con un administrador de paquetes, el más común es pip. Para instalar una paquetería con pip, se utiliza el siguiente comando en la terminal:

pip install nombre_paqueteria

O si se usa jupyter notebook o jupyter lab, se puede instalar una paquetería con el comando !pip install nombre_paqueteria.

Cada paqueteria tiene su propia documentación, por lo que es recomendable revisarla para conocer todas las funciones y características que ofrece.

Legibilidad y Documentación de Funciones

Es importante que las funciones sean fáciles de leer y entender. Para ello, es recomendable seguir las siguientes buenas prácticas:

  • Nombres descriptivos: Usa nombres descriptivos para las funciones y los parámetros.
  • Comentarios: Añade comentarios para explicar lo que hace cada parte de la función.
  • Documentación: Usa docstrings para documentar la función y proporcionar información sobre su propósito, los parámetros que espera y el valor que devuelve.
  • Dividir en funciones más pequeñas: Si una función es demasiado larga o hace demasiadas cosas, divídela en funciones más pequeñas que realicen tareas específicas.

Veamos un ejemplo de una función bien documentada y legible:

En este ejemplo, hemos definido una función sine_wave que genera una señal de onda sinusoidal con los parámetros de amplitud, frecuencia, fase, duración y tasa de muestreo especificados. Hemos documentado la función con un docstring que explica los parámetros que espera y el valor que devuelve. También hemos definido una función plot_signal que traza la señal generada. Esta función es más legible y fácil de entender gracias a los comentarios y la documentación.

Un ejemplo profesional de documentación de funciones es la documentación de la paquetería numpy, que proporciona una descripción detallada de cada función, los parámetros que espera y el valor que devuelve. Puedes consultar la documentación de numpy en el siguiente enlace: https://numpy.org/doc/stable/.

Estrucutras de Control

Las estructuras de control son bloques de código que permiten controlar el flujo de ejecución de un programa. En Python, las estructuras de control más comunes son los bucles for y while, y las declaraciones if, elif y else.

Estrucutras de Control: if, elif y else

La declaración if se utiliza para ejecutar un bloque de código si una condición es verdadera. La declaración elif se utiliza para comprobar múltiples condiciones si la condición anterior es falsa. La declaración else se utiliza para ejecutar un bloque de código si ninguna de las condiciones anteriores es verdadera.

Estructura de Control if

La sintaxis de la declaración if en python es la siguiente:

if condicion:
    # Código a ejecutar si la condición es verdadera
elif otra_condicion:
    # Código a ejecutar si la condición anterior es falsa y esta condición es verdadera
else:
    # Código a ejecutar si ninguna de las condiciones anteriores es verdadera

Ejemplo

Si tenemos varias condiciones que queremos comprobar, podemos usar la declaración elif para comprobarlas en orden. A continuación, se muestra un ejemplo de una declaración if con elif que comprueba si un número es positivo, negativo o cero:

Estrucutras de Control: Bucles for

El bucle for se utiliza para iterar sobre una secuencia de elementos, como una lista, una tupla o un rango de números. La sintaxis de un bucle for en Python es la siguiente:

for elemento in secuencia:
    # Código a ejecutar en cada iteración

Estructura de Control for

Son muy útiles cuando se necesita realizar una tarea repetitiva, como recorrer una lista de elementos o realizar una operación en cada elemento de una secuencia, serán vitales para el análisis de datos.

Ejemplo

Veamos un ejemplo donde imprimimos una cuenta regresiva desde 10 hasta 1:

Código
# Ejemplo de bucle for
for i in range(10, 0, -1):
    print(i)
10
9
8
7
6
5
4
3
2
1

La función range genera una secuencia de números desde el primer argumento hasta el segundo argumento, con un paso especificado por el tercer argumento. En este caso, estamos generando una secuencia de números desde 10 hasta 1 con un paso de -1. Es muy común usar range en bucles for. Otra forma de usar range es con un solo argumento, que genera una secuencia de números desde 0 hasta el argumento especificado.

Código
# Ejemplo de bucle for con un solo argumento
for i in range(5):
    print(i)
0
1
2
3
4

Como habras notado, la función range genera una secuencia de números desde 0 hasta 4, ya que el argumento especificado es 5, si cuentas los números, verás que son 5 números, si quieres hasta 5, debes poner 6.

En el siguiente tema abordaremos más los usos del ciclo for cuando trabajamos con listas y diccionarios o en general con objetos iterables.

Estrucutras de Control: Bucles while

El bucle while se utiliza para ejecutar un bloque de código mientras una condición sea verdadera. La sintaxis de un bucle while en Python es la siguiente:

while condicion:
    # Código a ejecutar mientras la condición sea verdadera

Estructura de Control while

Los bucles while son útiles cuando no se sabe cuántas veces se debe ejecutar un bloque de código y se necesita comprobar una condición en cada iteración.

ADVERTENCIA. Es importante tener cuidado al usar bucles while, ya que si la condición nunca se vuelve falsa, el bucle se ejecutará indefinidamente, lo que puede provocar un bucle infinito y bloquear el programa.

Ejemplo

Ahora intentemos algo más complicado, crearemos una función que nos diga cuantas vecces se repite una letra dada en una cadena de texto:

Código
def contar_letra(cadena, letra):
    contador = 0
    i = 0
    while i < len(cadena):
        if cadena[i] == letra:
            contador += 1
        i += 1
    return contador

# Primer verso y coro de "Army of One" de Coldplay 
cadena = """
Been around the world, wonders to view
Been around the world looking for someone like you
Pyramids try, Babylon too
But the beautifulest treasures lie in the deepest blue

So I never say die, aim never untrue
I'm never so high as when I'm with you
And there isn't a fire that I wouldn't walk through
My army of one is gonna fight for you
"""

letra = 'a'
print(f'La letra "{letra}" se repite {contar_letra(cadena, letra)} veces en la cadena de texto.')
La letra "a" se repite 14 veces en la cadena de texto.

Hemos combinado el uso de un bucle while con una declaración if para contar cuántas veces se repite una letra en una cadena de texto. En general siempre podemos usar un bucle for en lugar de un while, pero en este caso, queríamos mostrar cómo se puede usar un bucle while para realizar la misma tarea.

Combinar funciones, bucles y estructuras de control es una de las formas más poderosas de programar en cualquier lenguaje, y Python no es la excepción.

Ejercicios

  1. Escribe una función que tome dos números como argumentos y devuelva el mayor de los dos.

  2. Escribe una función que te diga si un número es par o impar.

  3. Crea una función que diga si una palabra es palíndroma o no.

  4. Crea una función que diga si un año es bisiesto o no. ( PISTA: un año es bisiesto si es divisible entre \(4\), excepto los años que son divisibles entre \(100\) pero no entre \(400\)).

  5. Escribe una función que cuente en reversa hasta 0 desde un número dado y si el número es divisible entre \(3\), imprime “Fizz”, si es divisible entre \(5\), imprime “Buzz” y si es divisible entre \(3\) y \(5\), imprime “FizzBuzz”. Por ejemplo, el número \(15\) debería imprimir “FizzBuzz”, el número \(9\) debería imprimir “Fizz” y el número \(10\) debería imprimir “Buzz”.

Manejando Bucles de Control

Hay ocasiones en las que necesitamos salir de un bucle antes de que se complete o saltar a la siguiente iteración sin ejecutar el resto del código. En Python, podemos hacer esto con las declaraciones break y continue.

Declaración break

La declaración break se utiliza para salir de un bucle antes de que se complete. Cuando se encuentra una declaración break, el bucle se detiene y la ejecución continúa con la siguiente instrucción después del bucle. La declaración break se puede utilizar en bucles for y while. Se suele utilizar para salir de un bucle cuando se cumple una condición específica utilizando una declaración if.

Supongamos que queremos encontrar el primer número divisible entre \(7\) y \(5\) en un rango de números del \(1\) al \(100\). Podemos usar un bucle for y la declaración break para salir del bucle cuando se encuentre el número deseado.

Código
for i in range(1, 101):
    if i % 7 == 0 and i % 5 == 0:
        print(f'El primer número divisible entre 7 y 5 es {i}')
        break
    else:
        print(f'{i} no es divisible entre 7 y 5')
1 no es divisible entre 7 y 5
2 no es divisible entre 7 y 5
3 no es divisible entre 7 y 5
4 no es divisible entre 7 y 5
5 no es divisible entre 7 y 5
6 no es divisible entre 7 y 5
7 no es divisible entre 7 y 5
8 no es divisible entre 7 y 5
9 no es divisible entre 7 y 5
10 no es divisible entre 7 y 5
11 no es divisible entre 7 y 5
12 no es divisible entre 7 y 5
13 no es divisible entre 7 y 5
14 no es divisible entre 7 y 5
15 no es divisible entre 7 y 5
16 no es divisible entre 7 y 5
17 no es divisible entre 7 y 5
18 no es divisible entre 7 y 5
19 no es divisible entre 7 y 5
20 no es divisible entre 7 y 5
21 no es divisible entre 7 y 5
22 no es divisible entre 7 y 5
23 no es divisible entre 7 y 5
24 no es divisible entre 7 y 5
25 no es divisible entre 7 y 5
26 no es divisible entre 7 y 5
27 no es divisible entre 7 y 5
28 no es divisible entre 7 y 5
29 no es divisible entre 7 y 5
30 no es divisible entre 7 y 5
31 no es divisible entre 7 y 5
32 no es divisible entre 7 y 5
33 no es divisible entre 7 y 5
34 no es divisible entre 7 y 5
El primer número divisible entre 7 y 5 es 35

Podemos ver que el bucle se detiene en el número \(35\), que es el primer número divisible entre \(7\) y \(5\) en el rango de números del \(1\) al \(100\).

Declaración continue

La declaración continue se utiliza para saltar a la siguiente iteración de un bucle sin ejecutar el resto del código en el bloque de bucle. Se suele utilizar para omitir ciertas iteraciones de un bucle basándose en una condición.

Por ejemplo, supongamos que queremos imprimir todos los números del \(1\) al \(10\) excepto el número \(5\). Podemos usar un bucle for y la declaración continue para saltar la iteración cuando el número es \(5\).

Código
for i in range(1, 11):
    if i == 5:
        continue
    print(i)
1
2
3
4
6
7
8
9
10

Otra declaración que se puede usar en bucles es pass, que no hace nada y se utiliza como marcador de posición cuando no se necesita ejecutar ninguna instrucción en un bloque de código. Pero el resultado no es el mismo que continue, ya que pass no salta a la siguiente iteración, simplemente no hace nada.

Código
for i in range(1, 11):
    if i == 5:
        pass
    print(i)
1
2
3
4
5
6
7
8
9
10

En este caso, el número \(5\) se imprimirá, pero no se ejecutará ninguna instrucción cuando i == 5. Es una forma de evitar errores de sintaxis cuando se necesita un bloque de código vacío (por ejemplo, en una declaración if o una función que aún no se ha implementado).

Conclusiones

En el contexto del análisis y el modelado de datos, ¿cómo crees que las funciones y las estructuras de control pueden ser útiles? ¿Qué tipos de tareas o problemas crees que se pueden abordar de manera más eficiente con funciones y estructuras de control?

En la próxima lección, exploraremos cómo trabajar con listas, tuplas, conjuntos y diccionarios en Python, que son estructuras de datos fundamentales para el análisis de datos y la programación en general. ¡Nos vemos en la próxima lección!

Volver arriba