Funciones

Una función es una sección de código reutilizable, escrita para realizar una tarea específica en un programa.

¿Por qué son útiles las funciones? Fíjate en los siguientes ejemplos.


In [1]:
# necesito calcular el cuadrado de un número
# defino una variable asignándole el valor 6
n = 6

# calculo el cuadrado y lo imprimo por pantalla
cuadrado = n**2
print(cuadrado)


36

In [2]:
# ahora me piden que calcule otro cuadrado, en este caso de 8
# repito el proceso
n = 8
cuadrado = n**2
print(cuadrado)


64

Imagina que por tercera vez, me piden que calcule un cuadrado. ¿Repito el proceso de manera indefinida?

El ejemplo es un poco extremo, pero sirve para ilustrar que, a veces, nuestros programas repiten siempre el mismo proceso (en este caso, un cálculo) variando los datos con los que trabajamos. En este caso, es mucho más eficaz reutilizar el código y adaptarlo ligeramente para generalizar el cálculo de cuadrados a cualquier número.

¿Me sigues? ¿Sí? Pues vamos a ver cómo hacerlo definiendo una función.

La sintaxis de una función forma un bloque de código de la siguiente manera:

def FUNCION(ENTRADA):
    """comentario explicando qué hace esta función"""
    SALIDA = INSTRUCCIONES
    return SALIDA


Las funciones se definen usando la instrucción def y están compuestas de tres partes:

  • El encabezado, que incluye la instrucción def, el nombre de la función, cualquier argumento que contenga la función especificado entre paréntesis (), y el signo de dos puntos :.
  • Una cadena de documentación con tres pares de comillas, que explica de forma breve qué hace la función.
  • El cuerpo, que es el bloque de código que describe los procedimientos que la función lleva a cabo. El cuerpo es un bloque de código y por eso aparece indentado (de igual forma que las sentencias if, elif, y else)
  • Una función siempre devuelve algo: una estructura de datos, un mensaje, etc. Por lo tanto, la última línea de cualquier función es una instrucción return.

Piensa en la función como una especie de artefacto o caja negra que toma una entrada, la manipula/procesa/convierte/modifica y devuelve un resultado.


In [3]:
# creamos una función llamada cuadrado que toma como entrada
# un número cualquiera y devuelve el cuadrado de dicho número

def cuadrado(numero):
    """devuelve el cuadrado del número especificado como entrada"""
    micuadrado = numero**2
    return micuadrado

In [4]:
# las variables definidas dentro de funciones limitan su alcance al interior de la funcion
# si tratas de utilizarlas fuera, es como si nunca las hubieras creado
# esta celda, da error
print(micuadrado)


---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-4-6741d8f167e8> in <module>()
      2 # si tratas de utilizarlas fuera, es como si nunca las hubieras creado
      3 # esta celda, da error
----> 4 print(micuadrado)

NameError: name 'micuadrado' is not defined

Una vez definida una función, podemos llamarla tantas veces sea necesario y ejecutarla en cualquier sitio de distintas maneras. Fíjate en los ejemplos:


In [5]:
print(cuadrado(6))

print(cuadrado(8+1))

print(cuadrado(3) + 1)

otroNumero = cuadrado(235.9)

print(otroNumero)


36
81
10
55648.810000000005

In [6]:
# en esta celda estoy ejecutando una función indicando un argumento de tipo cadena
# y falla porque la función reliza operaciones matemáticas que solo funcionan con números
print(cuadrado("a"))


---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-6-10e4f69ac453> in <module>()
      1 # en esta celda estoy ejecutando una función indicando un argumento de tipo cadena
      2 # y falla porque la función reliza operaciones matemáticas que solo funcionan con números
----> 3 print(cuadrado("a"))

<ipython-input-3-ccedda252d2c> in cuadrado(numero)
      4 def cuadrado(numero):
      5     """devuelve el cuadrado del número especificado como entrada"""
----> 6     micuadrado = numero**2
      7     return micuadrado

TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'int'

Fíjate por qué es importante añadir una cadena de texto entre comillas triples en nuestras funciones: sirve como documentación (docstring) de ayuda cuando utilizamos la función help() o accedemos a la ayuda de iPython.


In [7]:
cuadrado??

En realidad, ya conoces unas cuantas funciones que existen de manera predefinida en Python. ¿Recuerdas las funciones len() y type(), por ejemplo, para calcular la longitud y el tipo de las estructuras de datos? Ahora lo único que estamos haciendo es definiendo nuestras propias funciones.

Siguiendo con las operaciones, imagínate ahora que nos piden calcular cubos de distintos números, podríamos definir una función llamada cubo:


In [8]:
def cubo(numero):
    """devuelve el cubo del número especificado como entrada"""
    return numero**3

In [9]:
print(cubo(2))

# un millar es 10^3
millar = cubo(10)
print(millar)


8
1000

Podemos generalizar más y definir una función para calcular potencias, de manera que tomemos como entrada dos números, la base y el exponente.


In [10]:
def potencia(base, exponente):
    """calcula potencias"""
    return base**exponente

In [11]:
# calcula 10^2
print(potencia(10, 2))

# calcula 32^5
print(potencia(32, 5))

# un billón es un 10 seguido de 12 ceros
billon = potencia(10, 12)
print(billon)


100
33554432
1000000000000

Antes hemos mencionado que una función debía de devolver simpre algún valor, y por eso todas las definiciones de funciones terminan con una instrucción return. Bien, esto no era del todo cierto. Fíjate en este ejemplo.


In [12]:
def saludo():
    """Imprime un saludo por pantalla"""
    print("¡Hola, amigo!")

En esta celda utilizo la función range que no habíamos visto antes para indicar el número exacto de veces que quiero que se ejecute un bucle for.

Fíjate en cómo la función range, cuando se ejecuta con un único argumento N, devuelve una lista con N números sobre la que podemos iterar. Bueno, en realidad, esto no es correcto. La realidad es que devuelve una estructura de datos especial llamada iterador, con los números enteros entre el 0 y N-1). Pero para nuestros intereses, es mejor la primera explicación.


In [13]:
for i in range(3):
    saludo()
    
# fíjate cómo el valor de i se actualiza en cada iteración
for i in range(10):
    print("Voy por el número", i)


¡Hola, amigo!
¡Hola, amigo!
¡Hola, amigo!
Voy por el número 0
Voy por el número 1
Voy por el número 2
Voy por el número 3
Voy por el número 4
Voy por el número 5
Voy por el número 6
Voy por el número 7
Voy por el número 8
Voy por el número 9

range se puede ejecutar también con dos y tres argumenos numéricos. Cuando especificamos dos argumentos, podemos definir el primer y el último elemento de la lista resultante. Cuando especificamos tres, el último indica el salto entre cada par de elemenos. Fíjate en estos ejemplos.


In [14]:
# range devuelve los números entre el 10 al 19
for i in range(10, 20):
    print(i)
    
print("-------------------")

# range devuelve los números del 10 al 19, avanzando de 3 en 3
for i in range(10, 20, 3):
    print(i)


10
11
12
13
14
15
16
17
18
19
-------------------
10
13
16
19

In [15]:
range??

Obviamente, podemos definir funciones que hagan otras cosas diferentes a cálculo de potencias. Pensemos en un ejemplo de tratamiento de texto que nos puede resultar más útil.


In [16]:
def pluralize(word):
    """Convierte a plural cualquier palabra singular en inglés"""
    return word + "s"

¿Te atreves a modificar el código para:

  1. que funcionen correctamente las palabras acabadas en -s?
  2. manejar plurales irregulares?

In [17]:
print(pluralize("cat"))
print(pluralize("question"))

print(pluralize("berry"))
print(pluralize("business"))
print(pluralize("box"))
print(pluralize("flush"))
print(pluralize("coach"))

# plurales irregulares
print(pluralize("foot"))
print(pluralize("woman"))
print(pluralize("child"))


cats
questions
berrys
businesss
boxs
flushs
coachs
foots
womans
childs

In [18]:
def terminaEnVocal(palabra):
    """comprueba si una palabra termina en vocal"""
    vocales = "aeiou"
    if palabra[-1] in vocales:
        return True
    else:
        return False
    
    
print(terminaEnVocal("cava"))
print(terminaEnVocal("jamón"))


True
False

In [19]:
def convierteAMayusculaLaUltimaLetra(palabra):
    """devuelve la palabra transformando la última letra a mayúscula"""
    return palabra[:-1] + palabra[-1].upper() 
    
print(convierteAMayusculaLaUltimaLetra("cava"))
print(convierteAMayusculaLaUltimaLetra("jamón"))


cavA
jamóN

In [20]:
print("berry"[:-1] + "ies")


berries

In [21]:
def pluralize(word):    
    """Convierte a plural cualquier palabra singular en inglés"""
    if word.endswith("ss") or word.endswith("x"):
        return word + "es"
    else:
        return word + "s"