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.
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.
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.
def comparar_cinco(num):
if num < 5:
return "El número es menor que cinco"
elif num == 5:
return "El número es igual a cinco"
else:
return "El número es mayor que cinco"
print(comparar_cinco(2))
El número es menor que cinco
mi_numero = 7 # Aquí la variable se llama `mi_numero`
print(comparar_cinco(mi_numero)) # ¡Dentro de la función eso me da igual!
El número es mayor que cinco
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.
def sumatorio(num):
"""Suma los `num` primeros números.
Ejemplos
--------
>>> sumatorio(4)
10
"""
suma = 0
for nn in range(1, num + 1):
suma = nn + suma
return suma
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.
sumatorio(4)
10
help(sumatorio)
Help on function sumatorio in module __main__: sumatorio(num) Suma los `num` primeros números. Ejemplos -------- >>> sumatorio(4) 10
def sumatorio_mal(num):
for nn in range(1, num + 1):
suma = nn + suma
return suma
sumatorio_mal(4)
--------------------------------------------------------------------------- UnboundLocalError Traceback (most recent call last) <ipython-input-8-9882aa9a55e2> in <module>() ----> 1 sumatorio_mal(4) <ipython-input-7-d575a2b0e54e> in sumatorio_mal(num) 1 def sumatorio_mal(num): 2 for nn in range(1, num + 1): ----> 3 suma = nn + suma 4 return suma UnboundLocalError: local variable 'suma' referenced before assignment
Para comprobar el resultado correcto, nada como acudir a la función sum
de Python, que suma los elementos que le pasemos:
list(range(1, 4 + 1))
[1, 2, 3, 4]
sum(range(1, 4 + 1))
10
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.
def suma_tope(tope):
"""Suma números naturales consecutivos hasta un tope.
"""
suma = 0
nn = 1
while suma + nn <= tope:
suma = suma + nn
nn += 1
return suma
suma_tope(9)
6
suma_tope(9) == 1 + 2 + 3
True
suma_tope(10) == 1 + 2 + 3 + 4
True
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.
assert suma_tope(11) == 1 + 2 + 3 + 4
assert suma_tope(10 + 5) == 1 + 2 + 3 + 4
--------------------------------------------------------------------------- AssertionError Traceback (most recent call last) <ipython-input-16-7e20f9ee8a4a> in <module>() ----> 1 assert suma_tope(10 + 5) == 1 + 2 + 3 + 4 AssertionError:
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.
def cumple_normativa(tiempo, descanso):
"""Comprueba si un examen cumple la normativa de la UPM.
"""
if tiempo <= 3:
return True
else:
#if descanso:
# return True
#else:
# return False
return descanso # ¡Equivalente!
cumple_normativa(2, False)
True
if not cumple_normativa(5, descanso=False):
print("¡Habla con Delegación de Alumnos!")
¡Habla con Delegación de Alumnos!
Hallar $x = \sqrt{S}$.
http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method
def raiz(S):
x = S / 2
while True:
temp = x
x = (x + S / x) / 2
if temp == x:
return x
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.
raiz(10)
3.162277660168379
import math
math.sqrt(10)
3.1622776601683795
raiz(10) ** 2
9.999999999999998
math.sqrt(10) ** 2
10.000000000000002
Ahora tienes curiosidad, ¿verdad? :) http://puntoflotante.org/
Secuencia de Fibonacci: $F_n = F_{n - 1} + F_{n - 2}$, con $F_0 = 0$ y $F_1 = 1$.
$$0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, ...$$Con iteración:
def fib(n):
a, b = 0, 1
for i in range(n):
a, b = b, a + b # Bendita asignación múltiple
return a
fib(0), fib(3), fib(10)
(0, 2, 55)
Con recursión:
def fib_recursivo(n):
if n == 0:
res = 0
elif n == 1:
res = 1
else:
res = fib_recursivo(n - 1) + fib_recursivo(n - 2)
return res
Imprimir una lista con los $n$ primeros:
def n_primeros(n):
F = fib_recursivo
lista = []
for ii in range(n):
lista.append(F(ii))
return lista
n_primeros(10)
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
En esta clase hemos visto cómo crear funciones que encapsulen tareas de nuestro programa y las hemos aplicado para respondernos ciertas preguntas sencillas.
Referencias
Las siguientes celdas contienen configuración del Notebook
Para visualizar y utlizar los enlaces a Twitter el notebook debe ejecutarse como seguro
File > Trusted Notebook
%%html
<a href="https://twitter.com/AeroPython" class="twitter-follow-button" data-show-count="false">Follow @AeroPython</a>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script>
# Esta celda da el estilo al notebook
from IPython.core.display import HTML
css_file = '../static/styles/style.css'
HTML(open(css_file, "r").read())