{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\"AeroPython\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Clase 1b: Ejercicios prácticos" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "_En esta clase vamos a afianzar los conocimientos de Python que acabamos de adquirir haciendo algunos ejercicios, y así retener las peculiaridades de la sintaxis y aclarar algunos detalles a tener en cuenta cuando se trabaja en modo interactivo._" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Funciones" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Lo más importante para programar, y no solo en Python, es saber organizar el código en piezas más pequeñas que hagan tareas independientes y combinarlas entre sí. Las **funciones** son el primer nivel de organización del código: reciben unas *entradas*, las *procesan* y devuelven unas *salidas*." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![Black box](../static/blackbox.jpg)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Ejercicio 1: Función de una entrada" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Vamos a crear una función que compruebe si un número es mayor o menor que cinco. La salida ahora no nos importa mucho: lo importante es que al declarar los argumentos de entrada en la definición de la función, podremos usarlos dentro de ella con el nombre que decidamos." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
¡No olvides los dos puntos! Si el sangrado del código no avanza automáticamente, es que te los has dejado.
" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [], "source": [ "def comparar_cinco(num):\n", " if num < 5:\n", " return \"El número es menor que cinco\"\n", " elif num == 5:\n", " return \"El número es igual a cinco\"\n", " else:\n", " return \"El número es mayor que cinco\"" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "El número es menor que cinco\n" ] } ], "source": [ "print(comparar_cinco(2))" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "El número es mayor que cinco\n" ] } ], "source": [ "mi_numero = 7 # Aquí la variable se llama `mi_numero`\n", "print(comparar_cinco(mi_numero)) # ¡Dentro de la función eso me da igual!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
Apuntes:\n", "\n", "\n", "\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Ejercicio 2: Sumatorio" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Vamos a escribir ahora una función que sume los `n` primeros números naturales. Observa que podemos escribir una **cadena de documentación** (_docstring_) justo debajo de la definición de la función para explicar lo que hace." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [], "source": [ "def sumatorio(num):\n", " \"\"\"Suma los `num` primeros números.\n", "\n", " Ejemplos\n", " --------\n", " >>> sumatorio(4)\n", " 10\n", "\n", " \"\"\"\n", " suma = 0\n", " for nn in range(1, num + 1):\n", " suma = nn + suma\n", " return suma" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Lo que hemos hecho ha sido inicializar el valor de la suma a 0 e ir acumulando en ella los `num` primeros números naturales." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "10" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sumatorio(4)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on function sumatorio in module __main__:\n", "\n", "sumatorio(num)\n", " Suma los `num` primeros números.\n", " \n", " Ejemplos\n", " --------\n", " >>> sumatorio(4)\n", " 10\n", "\n" ] } ], "source": [ "help(sumatorio)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
Observa lo que sucede si no inicializamos la suma:
" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [], "source": [ "def sumatorio_mal(num):\n", " for nn in range(1, num + 1):\n", " suma = nn + suma\n", " return suma" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false }, "outputs": [ { "ename": "UnboundLocalError", "evalue": "local variable 'suma' referenced before assignment", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mUnboundLocalError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0msumatorio_mal\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m4\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[1;32m\u001b[0m in \u001b[0;36msumatorio_mal\u001b[1;34m(num)\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0msumatorio_mal\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mnum\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 2\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mnn\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mnum\u001b[0m \u001b[1;33m+\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 3\u001b[1;33m \u001b[0msuma\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mnn\u001b[0m \u001b[1;33m+\u001b[0m \u001b[0msuma\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 4\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[0msuma\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[1;31mUnboundLocalError\u001b[0m: local variable 'suma' referenced before assignment" ] } ], "source": [ "sumatorio_mal(4)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Para comprobar el resultado correcto, nada como acudir a la función `sum` de Python, que suma los elementos que le pasemos:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[1, 2, 3, 4]" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list(range(1, 4 + 1))" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "10" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sum(range(1, 4 + 1))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Ejercicio 3: Sumatorio con cota superior" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ahora nuestra función es un poco más rara: tiene que sumar los $n$ primeros números naturales y no pasarse de un determinado límite. Además, queremos el valor de la suma." ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false }, "outputs": [], "source": [ "def suma_tope(tope):\n", " \"\"\"Suma números naturales consecutivos hasta un tope.\n", "\n", " \"\"\"\n", " suma = 0\n", " nn = 1\n", " while suma + nn <= tope:\n", " suma = suma + nn\n", " nn += 1\n", " return suma" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "6" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "suma_tope(9)" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "suma_tope(9) == 1 + 2 + 3" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "suma_tope(10) == 1 + 2 + 3 + 4" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "La palabra clave `assert` recibe una expresión verdadera o falsa, y falla si es falsa. Si es verdadera no hace nada, con lo cual es perfecto para hacer comprobaciones a mitad del código que no estorben mucho." ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": false }, "outputs": [], "source": [ "assert suma_tope(11) == 1 + 2 + 3 + 4" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": false }, "outputs": [ { "ename": "AssertionError", "evalue": "", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mAssertionError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[1;32massert\u001b[0m \u001b[0msuma_tope\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m10\u001b[0m \u001b[1;33m+\u001b[0m \u001b[1;36m5\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m==\u001b[0m \u001b[1;36m1\u001b[0m \u001b[1;33m+\u001b[0m \u001b[1;36m2\u001b[0m \u001b[1;33m+\u001b[0m \u001b[1;36m3\u001b[0m \u001b[1;33m+\u001b[0m \u001b[1;36m4\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[1;31mAssertionError\u001b[0m: " ] } ], "source": [ "assert suma_tope(10 + 5) == 1 + 2 + 3 + 4" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Ejercicio 4: Normativa de exámenes" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "La normativa de exámenes de la UPM es: *\"si un examen dura más de 3 horas, entonces debe tener un descanso\"*. Los argumentos de la función son el tiempo en horas y un valor `True` o `False` que indica si hay descanso o no, y la función devuelve si el examen cumple o no con la normativa." ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "collapsed": false }, "outputs": [], "source": [ "def cumple_normativa(tiempo, descanso):\n", " \"\"\"Comprueba si un examen cumple la normativa de la UPM.\n", "\n", " \"\"\"\n", " if tiempo <= 3:\n", " return True\n", " else:\n", " #if descanso:\n", " # return True\n", " #else:\n", " # return False\n", " return descanso # ¡Equivalente!" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cumple_normativa(2, False)" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "¡Habla con Delegación de Alumnos!\n" ] } ], "source": [ "if not cumple_normativa(5, descanso=False):\n", " print(\"¡Habla con Delegación de Alumnos!\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Ejercicio 5" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Hallar $x = \\sqrt{S}$.\n", "\n", "1. $\\displaystyle \\tilde{x} \\leftarrow \\frac{S}{2}$.\n", "2. $\\displaystyle \\tilde{x} \\leftarrow \\frac{1}{2}\\left(\\tilde{x} + \\frac{S}{\\tilde{x}}\\right)$.\n", "3. Repetir (2) hasta que se alcance un límite de iteraciones o un criterio de convergencia.\n", "\n", "http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "collapsed": false }, "outputs": [], "source": [ "def raiz(S):\n", " x = S / 2\n", " while True:\n", " temp = x\n", " x = (x + S / x) / 2\n", " if temp == x:\n", " return x" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Aquí estoy usando un truco de la aritmética en punto flotante: como la convergencia se alcanza rápidamente, llega un momento en que el error es menor que la precisión de la máquina y el valor no cambia de un paso a otro." ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "3.162277660168379" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "raiz(10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
Se deja como ejercicio implementar otras condiciones de convergencia: error relativo por debajo de un umbral o número máximo de iteraciones.
" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "3.1622776601683795" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import math\n", "math.sqrt(10)" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "9.999999999999998" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "raiz(10) ** 2" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "10.000000000000002" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "math.sqrt(10) ** 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ahora tienes curiosidad, ¿verdad? :) http://puntoflotante.org/" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Ejercicio 6" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Secuencia de Fibonacci: $F_n = F_{n - 1} + F_{n - 2}$, con $F_0 = 0$ y $F_1 = 1$.\n", "\n", "$$0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, ...$$" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Con iteración:" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "collapsed": false }, "outputs": [], "source": [ "def fib(n):\n", " a, b = 0, 1\n", " for i in range(n):\n", " a, b = b, a + b # Bendita asignación múltiple\n", " return a" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(0, 2, 55)" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fib(0), fib(3), fib(10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Con recursión:" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "collapsed": false }, "outputs": [], "source": [ "def fib_recursivo(n):\n", " if n == 0:\n", " res = 0\n", " elif n == 1:\n", " res = 1\n", " else:\n", " res = fib_recursivo(n - 1) + fib_recursivo(n - 2)\n", " return res" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Imprimir una lista con los $n$ primeros:" ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "collapsed": false }, "outputs": [], "source": [ "def n_primeros(n):\n", " F = fib_recursivo\n", " lista = []\n", " for ii in range(n):\n", " lista.append(F(ii))\n", " return lista" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "n_primeros(10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "_En esta clase hemos visto cómo crear funciones que encapsulen tareas de nuestro programa y las hemos aplicado para respondernos ciertas preguntas sencillas._\n", "\n", "**Referencias**\n", "\n", "* Libro \"Learn Python the Hard Way\" http://learnpythonthehardway.org/book/\n", "* Python Tutor, para visualizar código Python paso a paso http://pythontutor.com/\n", "* Libro \"How To Think Like a Computer Scientist\" http://interactivepython.org/runestone/static/thinkcspy/toc.html\n", "* Project Euler: ejercicios para aprender Python https://projecteuler.net/problems\n", "* Python Challenge (!) http://www.pythonchallenge.com/" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Si te ha gustado esta clase:\n", "\n", "Tweet\n", "\n", "\n", "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "####

¡Síguenos en Twitter!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "###### Follow @AeroPython " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### \"Licencia
Curso AeroPython por Juan Luis Cano Rodriguez y Alejandro Sáez Mollejo se distribuye bajo una Licencia Creative Commons Atribución 4.0 Internacional." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "_Las siguientes celdas contienen configuración del Notebook_\n", "\n", "_Para visualizar y utlizar los enlaces a Twitter el notebook debe ejecutarse como [seguro](http://ipython.org/ipython-doc/dev/notebook/security.html)_\n", "\n", " File > Trusted Notebook" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "Follow @AeroPython\n", "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%html\n", "Follow @AeroPython\n", "" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "El estilo se ha aplicado =)\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Esta celda da el estilo al notebook\n", "from IPython.core.display import HTML\n", "css_file = '../static/styles/style.css'\n", "HTML(open(css_file, \"r\").read())" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.4.3" } }, "nbformat": 4, "nbformat_minor": 0 }