funciones en Python guía completa parámetros return

Funciones en Python — deja de repetir código de una vez

Las funciones en Python son la herramienta que te permite dejar de repetir código. Hasta ahora cada vez que necesitabas hacer lo mismo en dos sitios del programa copiabas y pegabas. Con funciones escribes el código una vez, le das un nombre, y lo llamas desde cualquier parte. Es uno de los conceptos más importantes de FP1 y el primero que realmente te hace sentir que estás programando en serio.

En este artículo vemos todo lo esencial: qué es una función, cómo pasar parámetros, qué hace return y qué pasa cuando no lo pones, y cómo las funciones pueden llamarse entre sí.

¿Qué es una función y por qué usarla?

Una función es un bloque de código con nombre que puedes ejecutar cuando quieras. La ventaja no es solo evitar repetición, es que hace el código más legible, más fácil de corregir y más fácil de reutilizar.

Imagina que en tu programa necesitas calcular el IVA en tres sitios distintos. Sin funciones:

# Sin funciones — repetición de código
precio1 = 100
iva1 = round(precio1 * 0.21, 2)

precio2 = 250
iva2 = round(precio2 * 0.21, 2)

precio3 = 75
iva3 = round(precio3 * 0.21, 2)

Si el IVA cambia del 21% al 23% tienes que cambiarlo en tres sitios. Con una función:

# Con funciones — escribes la lógica una vez
def calcular_iva(precio):
    return round(precio * 0.21, 2)

iva1 = calcular_iva(100)
iva2 = calcular_iva(250)
iva3 = calcular_iva(75)

Si el IVA cambia, solo tocas una línea, dentro de la función. Eso es el principio DRY: Don’t Repeat Yourself.

Cómo definir una función

La estructura básica de una función en Python es:

def nombre_funcion(parametros):
    # cuerpo de la función
    return valor    # opcional
  • def es la palabra reservada que le dice a Python que vas a definir una función
  • El nombre sigue las mismas reglas que las variables, minúsculas con guiones bajos
  • Los paréntesis son obligatorios aunque no haya parámetros
  • Los dos puntos : al final son obligatorios
  • El cuerpo va indentado con 4 espacios (Automático con la tecla Tab)
# Función sin parámetros
def saludar():
    print("Hola desde la función")

# Llamar a la función
saludar()    # → Hola desde la función

Parámetros y argumentos — la diferencia que nadie explica

Este es uno de los puntos que más confusión genera en FP1. La diferencia es sencilla:

Parámetro: la variable que defines en la función. Es el «hueco» que espera recibir un valor.

Argumento: el valor real que pasas cuando llamas a la función. Es lo que «rellena el hueco».

# 'nombre' es el PARÁMETRO — está en la definición
def saludar(nombre):
    print(f"Hola, {nombre}")

# "Sergio" es el ARGUMENTO — está en la llamada
saludar("Sergio")    # → Hola, Sergio
saludar("Sofía")     # → Hola, Sofía

Una función puede tener varios parámetros separados por comas:

def calcular_media(nota1, nota2, nota3):
    suma = nota1 + nota2 + nota3
    return suma / 3

media = calcular_media(7.5, 8.0, 6.5)
print(media)    # → 7.333...

Parámetros con valor por defecto

Puedes dar un valor por defecto a un parámetro para que sea opcional:

def saludar(nombre, saludo="Hola"):
    print(f"{saludo}, {nombre}")

saludar("Sergio")           # → Hola, Sergio
saludar("Sergio", "Buenos días")    # → Buenos días, Sergio

Si no pasas el argumento usa el valor por defecto. Los parámetros con valor por defecto siempre van al final.

El return — lo que más confunde

return es la instrucción que hace que la función devuelva un valor. Es el punto más confuso de las funciones en FP1.

def sumar(a, b):
    return a + b

resultado = sumar(3, 5)
print(resultado)    # → 8

El return hace dos cosas a la vez: devuelve el valor Y termina la función, NINGUNA línea después del return se ejecuta:

def ejemplo(x):
    if x > 0:
        return "positivo"
    return "negativo o cero"
    print("esto nunca se ejecuta")    # código muerto

¿Qué pasa cuando no pones return?

Esta es la pregunta que más veces escuché en clase. Si una función no tiene return, Python devuelve None automáticamente:

def saludar(nombre):
    print(f"Hola, {nombre}")    # solo imprime, no devuelve nada

resultado = saludar("Sergio")
print(resultado)    # → None

El error clásico es intentar usar el resultado de una función que no devuelve nada:

# MAL — saludar() no devuelve nada
nombre_en_mayusculas = saludar("Sergio").upper()    # AttributeError: 'NoneType'

# BIEN — si necesitas el valor, usa return
def saludar(nombre):
    return f"Hola, {nombre}"

resultado = saludar("Sergio").upper()    # → "HOLA, SERGIO"

La regla es simple: si necesitas usar el resultado de una función en otro sitio, usa return. Si solo necesitas que haga algo (como imprimir), no hace falta.

Funciones que llaman a otras funciones

Las funciones pueden llamarse entre sí, es la base de la programación modular. Cada función hace una cosa pequeña y bien, y las combinas para hacer cosas grandes:

def es_aprobado(nota):
    return nota >= 5.0

def clasificar_nota(nota):
    if nota >= 9:
        return "Sobresaliente"
    elif nota >= 7:
        return "Notable"
    elif es_aprobado(nota):    # llama a otra función
        return "Aprobado"
    else:
        return "Suspenso"

def analizar_estudiante(nombre, nota):
    clasificacion = clasificar_nota(nota)    # llama a otra función
    aprobado = es_aprobado(nota)             # llama a otra función
    print(f"{nombre}: {nota} → {clasificacion} ({'✓' if aprobado else '✗'})")

# Llamada principal
analizar_estudiante("Sergio", 7.5)    # → Sergio: 7.5 → Notable (✓)
analizar_estudiante("Sofía", 4.0)     # → Sofía: 4.0 → Suspenso (✗)

Fíjate en cómo analizar_estudiante llama a clasificar_nota que a su vez llama a es_aprobado. Cada función hace una sola cosa, eso es código limpio.

El validador reutilizable — el ejemplo que lo explica todo

Este es el ejemplo que mejor ilustra por qué las funciones son tan útiles. Sin funciones, validar una nota en varios sitios del programa significa repetir el mismo código:

# Sin funciones — repetición y difícil de mantener
nota1 = float(input("Nota 1: "))
while nota1 < 0 or nota1 > 10:
    print("Error: entre 0 y 10")
    nota1 = float(input("Nota 1: "))

nota2 = float(input("Nota 2: "))
while nota2 < 0 or nota2 > 10:
    print("Error: entre 0 y 10")
    nota2 = float(input("Nota 2: "))

Con una función:

# Con funciones — limpio y reutilizable
def pedir_nota(mensaje):
    nota = float(input(mensaje))
    while nota < 0 or nota > 10:
        print("Error: la nota debe estar entre 0 y 10")
        nota = float(input(mensaje))
    return nota

def pedir_texto(mensaje, min_chars=1):
    texto = input(mensaje)
    while len(texto) < min_chars:
        print(f"Error: mínimo {min_chars} caracteres")
        texto = input(mensaje)
    return texto

def pedir_entero(mensaje, minimo, maximo):
    while True:
        try:
            valor = int(input(mensaje))
            if minimo <= valor <= maximo:
                return valor
            print(f"Error: introduce un número entre {minimo} y {maximo}")
        except ValueError:
            print("Error: introduce un número entero válido")

# Usando las funciones — código limpio y legible
nombre = pedir_texto("Nombre del estudiante: ", min_chars=2)
nota1 = pedir_nota("Nota de Matemáticas (0-10): ")
nota2 = pedir_nota("Nota de Estadística (0-10): ")
nota3 = pedir_nota("Nota de Programación (0-10): ")
num_asignaturas = pedir_entero("¿Cuántas asignaturas en total? ", 1, 20)

media = (nota1 + nota2 + nota3) / 3
print(f"\n{nombre} — Media: {round(media, 2)}")

Si el rango de notas cambia, o quieres añadir más validaciones, solo tocas la función pedir_nota, el resto del código no cambia. Eso es el poder real de las funciones.

Alcance de las variables — local vs global

Las variables definidas dentro de una función solo existen dentro de ella, se llaman variables locales:

def mi_funcion():
    x = 10    # variable local — solo existe dentro de la función
    print(x)

mi_funcion()    # → 10
print(x)        # → NameError: name 'x' is not defined

Las variables definidas fuera de todas las funciones son globales y se pueden leer desde dentro:

MAXIMO = 10    # variable global

def validar(nota):
    return 0 <= nota <= MAXIMO    # puede leer MAXIMO

print(validar(7))    # → True

La regla práctica: define las constantes como variables globales en mayúsculas, y el resto de variables dentro de las funciones. Evita modificar variables globales desde dentro de funciones — es una fuente de bugs difíciles de encontrar.

Visualízalo con Python Tutor

Las funciones son el concepto donde Python Tutor más brilla, puedes ver exactamente cuándo se crea el «frame» de la función y cuándo desaparece. Copia esto en pythontutor.com:

def sumar(a, b):
    resultado = a + b
    return resultado

def calcular_media(n1, n2, n3):
    total = sumar(n1, n2)
    total = sumar(total, n3)
    return total / 3

media = calcular_media(7, 8, 6)
print(media)

Observa cómo cada llamada a función crea un nuevo frame con sus propias variables, y cómo ese frame desaparece cuando la función termina.

Resumen rápido

  • def nombre(parametros): define una función
  • Parámetro = el hueco en la definición. Argumento = el valor que pasas al llamar
  • return devuelve un valor Y termina la función
  • Sin return la función devuelve None
  • Las funciones pueden llamarse entre sí — cada una hace una cosa
  • Variables locales solo existen dentro de la función
  • DRY: escribe el código una vez, úsalo en muchos sitios

En el próximo artículo practicamos las funciones en Python construyendo programas modulares reales en VS Code.


Python functions — stop repeating code once and for all

Python functions are the tool that lets you stop repeating code. Until now, whenever you needed to do the same thing twice you copied and pasted. With functions you write the code once, give it a name, and call it from anywhere. This is one of the most important concepts in FP1, and the first one that makes you feel like you’re actually programming seriously.

What is a function and why use it?

A function is a named block of code you can run whenever you want. The advantage isn’t just avoiding repetition, it makes code more readable, easier to fix, and easier to reuse.

# Without functions — repeated code
price1 = 100
vat1 = round(price1 * 0.21, 2)
price2 = 250
vat2 = round(price2 * 0.21, 2)

# With functions — write the logic once
def calculate_vat(price):
    return round(price * 0.21, 2)

vat1 = calculate_vat(100)
vat2 = calculate_vat(250)

If VAT changes from 21% to 23%, you change one line. That’s the DRY principle: Don’t Repeat Yourself.

How to define a function

def function_name(parameters):
    # function body
    return value    # optional
  • def tells Python you’re defining a function
  • Parentheses are mandatory even with no parameters
  • Colon : at the end is mandatory
  • Body indented 4 spaces

Parameters vs arguments

Parameter: the variable in the function definition. The «slot» waiting for a value.

Argument: the actual value you pass when calling the function. What «fills the slot».

# 'name' is the PARAMETER — in the definition
def greet(name):
    print(f"Hello, {name}")

# "Sergio" is the ARGUMENT — in the call
greet("Sergio")    # → Hello, Sergio

Default parameter values

def greet(name, greeting="Hello"):
    print(f"{greeting}, {name}")

greet("Sergio")                  # → Hello, Sergio
greet("Sergio", "Good morning")  # → Good morning, Sergio

The return statement

return returns a value AND ends the function — nothing after it executes:

def add(a, b):
    return a + b

result = add(3, 5)
print(result)    # → 8

What happens without return?

Without return, Python automatically returns None:

def greet(name):
    print(f"Hello, {name}")    # prints but returns nothing

result = greet("Sergio")
print(result)    # → None

Classic mistake, trying to use the result of a function that returns nothing:

# WRONG — greet() returns None
upper = greet("Sergio").upper()    # AttributeError: 'NoneType'

# RIGHT — use return if you need the value
def greet(name):
    return f"Hello, {name}"

upper = greet("Sergio").upper()    # → "HELLO, SERGIO"

Rule: if you need to use the result elsewhere, use return. If you just need it to do something (like print), you don’t need it.

Functions calling other functions

def is_passing(grade):
    return grade >= 5.0

def classify_grade(grade):
    if grade >= 9:
        return "Outstanding"
    elif grade >= 7:
        return "Good"
    elif is_passing(grade):    # calls another function
        return "Passed"
    else:
        return "Failed"

def analyse_student(name, grade):
    classification = classify_grade(grade)
    passing = is_passing(grade)
    print(f"{name}: {grade} → {classification} ({'✓' if passing else '✗'})")

analyse_student("Sergio", 7.5)    # → Sergio: 7.5 → Good (✓)

Each function does one thing well — that’s clean code.

The reusable validator

def ask_grade(message):
    grade = float(input(message))
    while grade < 0 or grade > 10:
        print("Error: grade must be between 0 and 10")
        grade = float(input(message))
    return grade

def ask_text(message, min_chars=1):
    text = input(message)
    while len(text) < min_chars:
        print(f"Error: minimum {min_chars} characters")
        text = input(message)
    return text

def ask_integer(message, minimum, maximum):
    while True:
        try:
            value = int(input(message))
            if minimum <= value <= maximum:
                return value
            print(f"Error: enter a number between {minimum} and {maximum}")
        except ValueError:
            print("Error: enter a valid integer")

# Clean, readable code using the functions
name = ask_text("Student name: ", min_chars=2)
grade1 = ask_grade("Maths grade (0-10): ")
grade2 = ask_grade("Statistics grade (0-10): ")
grade3 = ask_grade("Programming grade (0-10): ")

average = (grade1 + grade2 + grade3) / 3
print(f"\n{name} — Average: {round(average, 2)}")

Variable scope — local vs global

def my_function():
    x = 10    # local — only exists inside the function
    print(x)

my_function()    # → 10
print(x)         # → NameError: name 'x' is not defined
MAXIMUM = 10    # global constant

def validate(grade):
    return 0 <= grade <= MAXIMUM    # can read MAXIMUM

Practical rule: define constants as global variables in UPPERCASE. Keep everything else inside functions.

Quick summary

  • def name(parameters): defines a function
  • Parameter = slot in definition. Argument = value you pass when calling
  • return returns a value AND ends the function
  • Without return the function returns None
  • Functions can call each other — each does one thing
  • Local variables only exist inside the function
  • DRY: write once, use everywhere

Publicaciones Similares

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *