################### Funciones en Python ################### Introducción a las funciones ============================ En Python, una función es un bloque de código reutilizable diseñado para realizar una tarea específica. Las funciones ayudan a descomponer programas complejos en partes más pequeñas y manejables, facilitando así la depuración, el mantenimiento y la reutilización del código. Para definir una función en Python, se utiliza la palabra clave def, seguida del nombre de la función, paréntesis que pueden contener parámetros (también conocidos como argumentos) y dos puntos. El cuerpo de la función, que contiene el código que se ejecuta cuando se llama a la función, se indentan bajo la línea de definición. Las funciones pueden devolver valores al lugar donde fueron llamadas utilizando la palabra clave return. Este mecanismo permite a las funciones procesar datos y luego pasar los resultados para su uso posterior en el programa. Una función sencilla -------------------- Para ilustrar cómo crear y usar funciones en Python, consideremos una función simple llamada ``saludar``. Esta función toma un nombre como parámetro y devuelve un saludo personalizado. La ventaja de usar funciones radica en su capacidad para encapsular código que realiza una tarea específica (en este caso, generar un saludo) y permitir su reutilización en diferentes partes del programa. Al llamar a la función ``saludar`` con un nombre específico, nos permite generar un mensaje de saludo personalizado para diferentes nombres sin necesidad de escribir el código de saludo cada vez. A continuación, se presenta una versión comentada de la función ``saludar``, donde se explican sus componentes básicos: .. sourcecode:: python :linenos: def saludar(nombre): """ Genera un saludo personalizado a partir del nombre proporcionado. :param nombre: Nombre de la persona a saludar. :type nombre: str :return: Un saludo personalizado. :rtype: str """ # La función toma un parámetro 'nombre', que se espera sea una cadena # de texto. # Crea un saludo personalizado utilizando el parámetro 'nombre'. mensaje = "¡Hola, " + nombre + "! Bienvenido." # Devuelve el mensaje de saludo. return mensaje # Ejemplo de cómo llamar a la función: print(saludar("Alicia")) # Otro ejemplo de cómo llamar la función saludo_pedro = saludar("Pedro") print(saludo_pedro) **Explicación Línea a Línea:** - **Línea 1**: Definición de la función. Esta línea inicia con la palabra clave ``def``, indicando el comienzo de la definición de la función llamada ``saludar``. Los paréntesis después del nombre de la función contienen los parámetros que recibe la función, en este caso, un solo parámetro llamado ``nombre``. - **Líneas 2 a 9**: Contienen el docstring de la función, que proporciona una descripción de lo que hace la función, los parámetros que acepta, y lo que retorna. - **Línea 13**: Esta línea construye el mensaje de saludo combinando el texto fijo con el parámetro ``nombre``, demostrando cómo se pueden manipular y concatenar cadenas de texto en Python. - **Línea 16**: La función finaliza retornando el mensaje de saludo construido. El uso de ``return`` permite que el valor generado por la función pueda ser usado en otra parte del programa. - **Línea 19**: Un ejemplo de cómo se puede llamar a la función ``saludar`` con el argumento "Alicia", lo que resultará en la impresión del mensaje de saludo personalizado para Alicia. - **Líneas 22-23**: Un segundo ejemplo de cómo se puede llamar a la función ``saludar`` con el argumento "Pedro", lo que resultará en la impresión del mensaje de saludo personalizado para Pedro. Aquí se muestra cómo se puede reutilizar la función sin tener que redefinirla. En este ejemplo se ilustra no solo cómo definir y usar funciones en Python, sino también la importancia de documentar adecuadamente el código a través de comentarios y docstrings para facilitar su comprensión y mantenimiento. .. note:: Los docstrings en Python son cadenas de texto utilizadas para documentar módulos, clases, métodos y funciones. Estas cadenas de documentación son accesibles en tiempo de ejecución a través de la propiedad ``__doc__`` o de la función ``help()`` y son una pieza clave para entender y utilizar correctamente el código. **Directivas más comunes en docstrings:** - **:param :** Describe un parámetro de la función o método. - **:type :** Especifica el tipo de un parámetro. - **:return:** Describe lo que devuelve la función o método. - **:rtype:** Especifica el tipo del valor que devuelve la función o método. Incluir ejemplos de uso en los docstrings es una práctica altamente recomendada, aunque opcional. Los ejemplos ofrecen una guía rápida de cómo se espera que se utilice una función o clase, y pueden ser particularmente útiles para aclarar casos de uso complejos o menos obvios. Aquí se muestra cómo incluir ejemplos en un docstring: .. sourcecode:: python def suma(a, b): """ Suma dos números y devuelve el resultado. :param a: Primer número. :type a: int, float :param b: Segundo número. :type b: int, float :return: La suma de `a` y `b`. :rtype: int, float **Ejemplo de uso:** >>> suma(2, 3) 5 >>> suma(2.5, 3.0) 5.5 """ return a + b Los ejemplos no solo facilitan la comprensión del propósito y uso de la función, sino que también pueden servir como tests simples si se utilizan junto con herramientas de doctest en Python, que permiten verificar que los ejemplos en los docstrings se ejecuten correctamente. Al documentar tu código con docstrings y seguir las convenciones establecidas, haces que sea más accesible y fácil de usar tanto para ti como para otros desarrolladores. Ejemplo de cómo escribir un programa que utilice funciones ========================================================== Imaginemos que queremos desarrollar un programa cuyo objetivo es imprimir todos los números primos menores a un número especificado por el usuario. Para lograr este objetivo, es esencial desglosar el problema en tareas más pequeñas y manejables, las cuales pueden ser resueltas mediante el uso de funciones. A continuación, identificamos las funciones necesarias para nuestro programa: 1. **Función es_primo**: Esta función es fundamental para nuestro programa. Recibirá un número como parámetro y retornará ``True`` si el número es primo, o ``False`` en caso contrario. Su propósito es determinar la primalidad de un número dado. 2. **Función imprimir_primos_menores**: Esta función será responsable de imprimir los números primos menores a un número proporcionado. Tomará como parámetro un número y, utilizando un bucle junto con la función ``es_primo``, imprimirá los números primos menores a dicho número. 3. **Función de inicio**: Necesitamos una función principal que sirva como punto de entrada a nuestro programa. Esta función se encargará de solicitar el número límite para la búsqueda de números primos y, finalmente, ejecutar la función ``imprimir_primos_menores`` para mostrar los resultados. Al estructurar nuestro programa en torno a estas funciones, no solo hacemos el código más legible y organizado, sino que también facilitamos su mantenimiento y la posibilidad de reutilizar código en futuros proyectos. Este enfoque modular es una práctica recomendada en la programación y resulta especialmente útil en la resolución de problemas complejos. Función ``es_primo`` -------------------- La primer función que se necesita es una diseñada para determinar si un número dado es primo. Un número primo es aquel que solo es divisible por 1 y por sí mismo, lo que implica que no tiene divisores aparte de estos dos números. La estrategia para verificar la primalidad consiste en comprobar si el número es divisible por cualquier número desde 2 hasta la raíz cuadrada del número en cuestión. Esta es una manera eficiente de reducir el número de divisiones necesarias para determinar la primalidad. .. sourcecode:: python :linenos: def es_primo(n): """ Determina si un número es primo. Realiza la comprobación dividiendo el número `n` por todos los números mayores que 1 y menores o iguales a la raíz cuadrada de `n`. Si `n` es divisible por cualquiera de estos números, entonces no es primo. :param n: El número a verificar. :type n: int :return: True si el número es primo, False en caso contrario. :rtype: bool **Referencias:** - "Introduction to Algorithms" por Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, y Clifford Stein. - Wikipedia: https://en.wikipedia.org/wiki/Prime_number **Ejemplo de uso:** >>> es_primo(5) True >>> es_primo(4) False >>> es_primo(11) True """ if n <= 1: return False divisor = 2 while divisor * divisor <= n: if n % divisor == 0: return False divisor += 1 return True En el docstring de esta función, se incluyen además referencias para aquellos interesados en profundizar en los fundamentos algorítmicos detrás de la verificación de números primos. La sección de ejemplos de uso demuestra cómo aplicar la función en casos concretos, facilitando su comprensión y verificación. Función imprimir_primos_menores ------------------------------- Para complementar nuestra herramienta de detección de números primos, requerimos una función que se encargue de evaluar todos los números enteros hasta un límite especificado por el usuario. La función ``imprimir_primos_menores`` cumple con este propósito al hacer uso de la función ``es_primo`` previamente definida. Su objetivo es iterar a través de todos los números enteros menores o iguales al número proporcionado, verificar la primalidad de cada uno mediante ``es_primo``, y posteriormente imprimir aquellos que sean primos. .. sourcecode:: python :linenos: def imprimir_primos_menores(limite): """ Imprime todos los números primos menores o iguales a un límite dado. Utiliza la función `es_primo` para evaluar la primalidad de cada número en el rango hasta `limite`, incluido, imprimiendo aquellos que resulten ser primos. :param limite: El número hasta el cual buscar números primos. :type limite: int **Ejemplo de uso:** >>> imprimir_primos_menores(10) 2 3 5 7 """ numero = 2 while numero <= limite: if es_primo(numero): print(numero) numero = numero+1 La inclusión de esta función en nuestro programa permite ofrecer una funcionalidad integral para la identificación y presentación de números primos hasta un punto definido. Resulta particularmente útil para aquellos interesados en la teoría de números o en la aplicación de conceptos matemáticos básicos en programación. Función de inicio ----------------- La pieza final de nuestro programa es la función de inicio, comúnmente definida como ``main``. Esta función actúa como el punto de entrada de nuestro programa, donde todas las operaciones inician. Su tarea es interactuar con el usuario, solicitándole que ingrese un número hasta el cual desea buscar números primos. Posteriormente, hace uso de la función ``imprimir_primos_menores`` para llevar a cabo la tarea de identificar e imprimir los números primos menores al número proporcionado por el usuario. .. sourcecode:: python :linenos: def main(): """ Función principal del programa que solicita al usuario ingresar un número. Esta función guía al usuario para que ingrese un número y luego utiliza la función `imprimir_primos_menores` para imprimir todos los números primos menores a ese número ingresado. **Ejemplo de uso:** Al ejecutar el programa, se pedirá al usuario: >> Ingrese un número: 10 Y el programa imprimirá: 2 3 5 7 """ numero_ingresado = int(input("Ingrese un número: ")) imprimir_primos_menores(numero_ingresado) if __name__ == "__main__": main() La instrucción ``if __name__ == "__main__":`` asegura que el bloque de código dentro de ``main()`` solo se ejecute cuando el script sea el archivo principal ejecutado, lo que permite que este código sea importado como un módulo sin ejecutar ``main()`` automáticamente. Esta práctica es una convención común en Python para separar la ejecución del programa de su importación como módulo, facilitando la reutilización y la modularidad del código. El código completo del programa sería: .. sourcecode:: python :linenos: #!/usr/bin/python3 # -*- coding: utf8 -*- def es_primo(n): """ Determina si un número es primo. Realiza la comprobación dividiendo el número `n` por todos los números mayores que 1 y menores o iguales a la raíz cuadrada de `n`. Si `n` es divisible por cualquiera de estos números, entonces no es primo. :param n: El número a verificar. :type n: int :return: True si el número es primo, False en caso contrario. :rtype: bool **Referencias:** - "Introduction to Algorithms" por Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, y Clifford Stein. - Wikipedia: https://en.wikipedia.org/wiki/Prime_number **Ejemplo de uso:** >>> es_primo(5) True >>> es_primo(4) False >>> es_primo(11) True """ if n <= 1: return False divisor = 2 while divisor * divisor <= n: if n % divisor == 0: return False divisor += 1 return True def imprimir_primos_menores(limite): """ Imprime todos los números primos menores o iguales a un límite dado. Utiliza la función `es_primo` para evaluar la primalidad de cada número en el rango hasta `limite`, incluido, imprimiendo aquellos que resulten ser primos. :param limite: El número hasta el cual buscar números primos. :type limite: int **Ejemplo de uso:** >>> imprimir_primos_menores(10) 2 3 5 7 """ numero = 2 while numero <= limite: if es_primo(numero): print(numero) numero = numero+1 def main(): """ Función principal del programa que solicita al usuario ingresar un número. Esta función guía al usuario para que ingrese un número y luego utiliza la función `imprimir_primos_menores` para imprimir todos los números primos menores a ese número ingresado. **Ejemplo de uso:** Al ejecutar el programa, se pedirá al usuario: >>> Ingrese un número: 10 Y el programa imprimirá: 2 3 5 7 """ numero_ingresado = int(input("Ingrese un número: ")) imprimir_primos_menores(numero_ingresado) if __name__ == "__main__": main() .. admonition:: Pregunta ¿Que modificación hay que hacerle a este programa para que corra desde una consola de Jupiter o Colab? Ejercicios ^^^^^^^^^^ Modificaciones al Programa de Números Primos --------------------------------------------- A continuación, se presentan 10 problemas que pueden ser resueltos mediante modificaciones menores a los programas de números primos previamente descritos: 1. **Encontrar los primeros N números primos**: Modificar el programa para que, en lugar de buscar números primos menores a un número dado, busque los primeros N números primos. 2. **Suma de números primos**: Adaptar el programa para que calcule y muestre la suma de todos los números primos menores a un número dado. 3. **Verificar si un número es primo y mostrar sus divisores si no lo es**: Modificar ``es_primo`` para que, además de devolver si un número es primo, imprima los divisores del número si este no es primo. 4. **Números primos gemelos**: Adaptar el programa para identificar y mostrar pares de números primos gemelos (dos primos que se diferencian en dos) menores a un número dado. 5. **Factorización prima de un número**: Crear una función que tome un número y devuelva sus factores primos. 6. **Números primos en un rango**: Modificar ``imprimir_primos_menores`` para que el usuario pueda especificar un rango de búsqueda, es decir, encontrar primos entre dos números dados. 7. **Contar números primos**: Cambiar el programa para que, en lugar de imprimir los números primos, cuente cuántos números primos hay menores a un número dado y muestre este total. 8. **El primo más cercano**: Implementar una función que encuentre el número primo más cercano a un número dado, ya sea mayor o menor. Otros Ejercicios Sencillos que utilizan Funciones ------------------------------------------------- 1. **Calcular el factorial de un número**: Desarrollar una función que tome como entrada un número entero y devuelva su factorial. 2. **Encontrar el máximo común divisor (MCD) de dos números**: Implementar una función que calcule y retorne el MCD de dos números enteros. 3. **Calcular la potencia de un número**: Crear una función para calcular la potencia de un número (base) elevado a un exponente entero positivo mediante multiplicaciones sucesivas. En Python, una función puede recibir múltiples parámetros simplemente separándolos con comas en la definición de la función. Por ejemplo: .. sourcecode:: python def calcular_potencia(base, exponente): # cuerpo de la función aquí ... Esta función recibe dos parámetros, que contendrán los valores numéricos de la base y del exponente, y que pueden ser utilizados para calcular el resultado pedido. 4. **Convertir grados Celsius a Fahrenheit**: Diseñar una función que convierta una temperatura dada en grados Celsius a Fahrenheit. 5. **Calcular el área de un círculo**: Escribir una función que calcule el área de un círculo dado su radio como argumento. 6. **Determinar si un año es bisiesto**: Desarrollar una función que determine si un año (dado como número entero) es bisiesto o no. 7. **Calcular la suma de una serie aritmética**: Implementar una función que calcule la suma de los primeros N términos de una serie aritmética. 8. **Determinar la distancia entre dos puntos en el plano**: Implementar una función que calcule la distancia entre dos puntos dados sus coordenadas (x1, y1) y (x2, y2). Este problema ilustra cómo se pueden pasar múltiples parámetros a una función, como se muestra en la siguiente línea de definición de la función: .. sourcecode:: python def distancia_entre_puntos(x1, y1, x2, y2): """ Calcula la distancia entre dos puntos en el plano. :param x1: Coordenada x del primer punto. :param y1: Coordenada y del primer punto. :param x2: Coordenada x del segundo punto. :param y2: Coordenada y del segundo punto. :return: La distancia entre los puntos. """ Esta función recibe cuatro parámetros, que representan las coordenadas de dos puntos en el plano, y puede ser utilizada para calcular la distancia euclidiana entre ellos.