Modulo 04: Funciones en Python

Idea central

En Python una funcion se define con def, no necesita prototipo, puede devolver varios valores a la vez con una tupla, y los parametros pueden tener valores por defecto. El bloque de la funcion se delimita solo por indentacion, no por llaves.


Que aprendes

ConceptoPara que sirve
def nombre(params):Declarar una funcion
return valorDevolver un resultado
Parametros con valor por defectoHacer parametros opcionales
Docstring ("""...""")Documentar la funcion (visible con help())
return a, b (tupla)Devolver varios valores en una sola instruccion
Sin prototipoNo hay separacion declaracion/definicion

C vs Python

El MISMO ejemplo — funcion que suma dos enteros y la llama:

CPython
int suma(int a, int b) {def suma(a, b):
return a + b; return a + b
}(fin de bloque por indentacion)
int main() {(no hay main obligatorio)
int r = suma(3, 4);r = suma(3, 4)
printf("%d\n", r);print(r)
return 0;
}

Diferencias clave:

AspectoCPython
Tipo del retornoint suma(...) — obligatorioninguno; Python infiere
Tipo de parametrosint a, int b — obligatoriosolo el nombre
Delimitador de bloque{ }indentacion (4 espacios)
Prototiponecesario si la funcion va despues de mainno existe
Devolver varios valoresstruct o punterosreturn a, b — tupla automatica
Documentacioncomentario manualdocstring """..."""

Explicacion

Patron basico

def nombre_funcion(param1, param2):
    """Docstring: una frase que describe que hace."""
    # cuerpo
    return resultado

La indentacion es la sintaxis. Si olvidas indentar, obtienes IndentationError.

Parametros con valor por defecto

def potencia(base, exp=2):
    """Eleva base a exp; por defecto exp=2."""
    return base ** exp
 
print(potencia(3))     # 9  (exp usa el default)
print(potencia(3, 3))  # 27

Regla: los parametros con default van siempre al final de la lista.

Devolver varios valores

def minmax(lista):
    """Devuelve (minimo, maximo) de la lista."""
    return min(lista), max(lista)
 
pequeno, grande = minmax([4, 1, 9, 2])
print(pequeno, grande)  # 1 9

return a, b crea una tupla (a, b). El desempaquetado x, y = funcion() es idiomatico en Python.

Docstring

def es_par(n):
    """Devuelve True si n es par, False si es impar."""
    return n % 2 == 0
 
help(es_par)   # muestra el docstring en consola

Worked example

Enunciado: escribe factorial(n) que devuelva n! para n >= 0. Luego pide un numero al usuario e imprime su factorial.

Paso 1 — esquema de la funcion:

def factorial(n):
    """Devuelve n! (n factorial). n debe ser >= 0."""

Paso 2 — caso base: si n == 0, el resultado es 1.

    if n == 0:
        return 1

Paso 3 — caso general: multiplicar n por factorial(n-1) (iterativo para evitar recursion por ahora).

    resultado = 1
    for i in range(2, n + 1):
        resultado *= i
    return resultado

Paso 4 — llamada con input:

numero = int(input("Introduce un entero >= 0: "))
print(f"{numero}! = {factorial(numero)}")

Funcion completa:

def factorial(n):
    """Devuelve n! (n factorial). n debe ser >= 0."""
    if n == 0:
        return 1
    resultado = 1
    for i in range(2, n + 1):
        resultado *= i
    return resultado
 
numero = int(input("Introduce un entero >= 0: "))
print(f"{numero}! = {factorial(numero)}")

Ejecucion de ejemplo:

Introduce un entero >= 0: 5
5! = 120

Errores tipicos de Python

  1. IndentationError por mezclar tabs y espacios. Python 3 no permite mezclarlos. Usa siempre 4 espacios. Configura tu editor para insertar espacios al pulsar Tab.

  2. Olvidar return y usar el resultado.

    def doble(x):
        x * 2          # calcula pero NO devuelve nada
     
    print(doble(5))    # None  <-- sorpresa

    En C el compilador avisa; en Python el None silencioso pasa desapercibido.

  3. Parametros con default mutables (trampa clasica).

    def agregar(item, lista=[]):   # MAL: lista compartida entre llamadas
        lista.append(item)
        return lista
     
    # Correcto:
    def agregar(item, lista=None):
        if lista is None:
            lista = []
        lista.append(item)
        return lista
  4. No convertir input() antes de operar.

    n = input("Numero: ")
    print(factorial(n))   # TypeError: range() integer argument expected, not str

    Siempre int(input(...)) o float(input(...)).

  5. Llamar a la funcion antes de definirla (en script). En C el prototipo te salva. En Python el orden de ejecucion del script importa: si llamas a factorial(5) en la linea 2 y defines factorial en la linea 10, obtienes NameError. Solucion: pon las definiciones al principio, o usa el patron if __name__ == "__main__":.


Ejercicios

Cada ejercicio tiene dos ficheros en practica/04-funciones/:

NEnunciadoDificultadSalida esperada (ejemplo)
01Escribe es_par(n) que devuelva True/False. Pide un numero al usuario e imprime si es par o impar.(facil) facil8 es par: True
02Escribe max_de_dos(a, b) que devuelva el mayor. Pide dos numeros e imprime el mayor (sin usar max()).(facil) facilEl mayor de 7 y 3 es: 7
03Escribe factorial(n) iterativo. Pide n al usuario e imprime n!.(media) medio5! = 120
04Escribe potencia(base, exp=2) usando un bucle (sin **). Pide base y exponente; si el usuario no da exponente, usa 2.(media) medio3 ^ 4 = 81
05Escribe es_primo(n) que devuelva True/False. Pide un numero e indica si es primo.(media) medio7 es primo: True
06Escribe minmax(lista) que devuelva una tupla (minimo, maximo). Pide al usuario 5 numeros separados por espacios, llama a la funcion e imprime el resultado.(dificil) avanzadoMin: 1 Max: 9

Ficheros:

  • practica/04-funciones/ej01_practica.py / ej01_modelo.py
  • practica/04-funciones/ej02_practica.py / ej02_modelo.py
  • practica/04-funciones/ej03_practica.py / ej03_modelo.py
  • practica/04-funciones/ej04_practica.py / ej04_modelo.py
  • practica/04-funciones/ej05_practica.py / ej05_modelo.py
  • practica/04-funciones/ej06_practica.py / ej06_modelo.py

Conexiones