Parámetros y return
En resumen: Un parámetro es una variable de la función que recibe el valor pasado en la llamada (el argumento), y return devuelve un resultado a quien hace la llamada.
Problema
Un recibo, totales distintos
Quieres una función que imprima la última línea del recibo: «Total: … €». Pero el total es distinto en cada pedido.
Las funciones de la lección anterior imprimen siempre lo mismo. Una función print_total() no tiene de dónde saber el total. Tampoco quieres una función aparte para cada total. Necesitas una forma de pasar el total a la función cuando la llamas.
La idea
Parámetros: lo que recibe la función
Entre paréntesis escribes un nombre para lo que la función espera. Eso es un parámetro. Dentro de la función es una variable normal.
Al hacer la llamada, pones el valor entre paréntesis. Ese valor se llama argumento.
def print_total(total): print(f"Total: {total} €")
print_total(12.5)print_total(4.2)Total: 12.5 €Total: 4.2 €total es el parámetro. 12.5 y 4.2 son los argumentos. Hay una sola función, y imprime totales distintos.
Delante del parámetro no se escribe un tipo: Python no comprueba lo que pasas. Si pasas un texto en lugar de un número, la función lo imprime sin quejarse. Por eso el nombre del parámetro tiene que decir con claridad qué se espera.
Si hay varios parámetros, los separas con comas. Los argumentos se pasan en el mismo orden.
Pruébalo
Por posición, no por nombre
¿Qué imprimirá el programa?
def print_line(item, qty): print(f"{item}: {qty} uds.")
coffee = "Café"qty = 3print_line(coffee, 2)Los argumentos se asocian con los parámetros por posición: el primero con item, el segundo con qty. La variable qty de fuera no tiene nada que ver con el parámetro qty, aunque se llamen igual.
Problema
¿Por qué no bajó el precio?
Has escrito una función para un descuento del 10% y la has llamado:
def apply_discount(price): price = price * 0.9
price = 100apply_discount(price)print(price) # 100100El precio sigue siendo 100. La función no da ningún error, y aun así el descuento no está. ¿Adónde fue?
Míralo
La función recibe el valor
def apply_discount(price): price = price * 0.9
price = 100apply_discount(price)print(price) # 100Paso a paso, en palabras
- En el programa hay una variable price = 100.
- Llamas a apply_discount(price): se reserva memoria nueva para la función.
- Su parámetro price recibe el valor 100.
- La función calcula 100 * 0.9 = 90 y guarda el nuevo número en su propio price.
- La función termina y su memoria desaparece, junto con su price.
- Y price en el programa sigue siendo 100.
Al llamarla, la función no recibe la variable price en sí, sino su valor, en su propia variable price. La línea price = price * 0.9 pone el nuevo número 90 en la variable de la función. Cuando la función termina, su memoria desaparece, y ese 90 con ella. Fuera no ha cambiado nada: es como si la función hubiera recibido una copia. Esto se llama paso por valor.
Las dos variables se llaman igual (price) a propósito: es justo lo que confunde en la práctica. El nombre no importa. Cada función tiene sus propias variables.
Más precisamente, para curiosos
Hablando con precisión, Python no copia el número. El parámetro apunta al mismo número 100 al que apunta price fuera. Pero un número no se puede cambiar en su sitio: price = … solo hace que el nombre de la función apunte a otro número, y price fuera sigue apuntando a 100. Por eso, con números y textos, el resultado es el mismo que con una copia. Con las listas es distinto: la función puede cambiar la propia lista (por ejemplo, con append), y el cambio se ve también fuera:
def add_item(items): items.append("leche")
cart = ["pan"]add_item(cart)print(cart)['pan', 'leche']La idea
return: la función devuelve un resultado
La solución es que la función devuelva el nuevo precio. En el cuerpo escribes return y el valor. El tipo del resultado no se escribe: def es igual tanto si la función devuelve algo como si no.
def apply_discount(price): return price * 0.9
price = 100price = apply_discount(price)print(price) # 90.0Paso a paso, en palabras
- En el programa: price = 100.
- Llamas a apply_discount(price): se reserva memoria para la función.
- El parámetro price recibe el valor 100.
- return price * 0.9: el resultado es 90.
- El resultado vuelve al programa y se guarda en price.
- Ahora price en el programa es 90.
La llamada apply_discount(price) ahora es un valor. Puedes guardarlo en una variable (como aquí), imprimirlo o hacer cálculos con él.
Más precisamente, para curiosos
- Una función sin
returntambién devuelve algo:None, el valor «nada». Si imprimes el resultado de la primera versión, que solo rebajaba su propia copia, eso es justo lo que ves:
def apply_discount(price): price = price * 0.9
print(apply_discount(100))None- También puedes escribir
returnsin valor. Simplemente termina la función.
- Una función puede devolver varios valores a la vez: los escribes separados por comas después de
return, y en la llamada los guardas en otras tantas variables:
def get_limits(): return 1, 10
low, high = get_limits()print(low, high)1 10Pruébalo
¿Cuál es el resultado?
La función calcula un IVA del 20% sobre el precio. ¿Qué tiene que ir en el hueco para que quien la llama reciba el resultado?
def vat(price):
price * 0.2return: sin él, la función calcula price * 0.2 y tira el resultado, y la llamada da None.Pruébalo
Devuelto, pero perdido
¿Qué imprimirá el programa?
def reserve(seats): seats = seats - 2 print(f"dentro: {seats}") return seats
seats = 10reserve(seats)print(f"fuera: {seats}")La función cambia su propia variable y devuelve 8, pero nadie guarda el resultado. Para conservarlo, necesitas seats = reserve(seats).
La idea
return termina la función
La tienda no cobra el envío en los pedidos de 50 € o más. Si no, el envío cuesta 4,99 €:
def shipping_cost(total): if total >= 50: return 0 return 4.99
print(shipping_cost(62.0))print(shipping_cost(18.5))04.99En cuanto llega a return, la función termina en ese momento. Por eso, con 62 €, el segundo return no se ejecuta, y no necesitamos un else.
Una función con resultado tiene que devolver un valor en cada camino. Pero Python no lo comprueba. Si quitas la última línea, el programa se ejecuta, y para un pedido de 18,50 € la función llega a su final sin un return y devuelve None:
def shipping_cost(total): if total >= 50: return 0
print(shipping_cost(62.0))print(shipping_cost(18.5))0NoneNo hay error, así que un descuido así cuesta de detectar. Fíjate en la salida y prueba cada camino de la función.
Pruébalo
Encuentra el error
Los socios del club tienen un 10% de descuento, y los demás pagan el precio completo. Pero todos reciben el descuento. ¿En qué línea está el error?
Elige la línea con el error.
El último return es para quienes no son socios: pagan el precio completo, return price.
Ejercicio
Funciones que calculan
Resuelve las tareas en tu editor. Cada función recibe lo que necesita como parámetros y devuelve el resultado. La impresión se hace fuera de las funciones, en las líneas de debajo.
1. Media aritmética. La función average(values) devuelve la media de los números de la lista. Debajo, lee del teclado cuántos números hay y después los números.
51015202530Media: 20.02. Número primo. La función is_prime(n) devuelve si el número es primo (divisible solo por 1 y por sí mismo). Para 7 devuelve True, para 12 False.
3. Temperaturas. Las funciones to_fahrenheit(c) y to_celsius(f). F = C · 9 / 5 + 32. Lee una temperatura y una unidad (C o F) e imprime la temperatura convertida.
100C100.0 C = 212.0 F4. Calculadora. La función calculate(a, b, op) devuelve el resultado para +, -, * o /. La operación se elige con if.
105+10.0 + 5.0 = 15.05. Un triángulo con parámetro. Lo prometimos en la lección anterior. La función print_triangle(height) imprime un triángulo rectángulo de asteriscos con altura height. Para 3:
** ** * *Más precisamente, para curiosos
En Python, / siempre da un número decimal, así que 5 / 9 es 0.5555…, no 0 como en Java y C#. La división entera es //:
print(5 / 9)print(7 // 2)0.55555555555555563Ejercicio
Funciones para listas
Cada tarea es una función que recibe una lista (o una palabra) y devuelve un resultado. Al final, júntalas todas en un programa.
total,sum_evenysum_odd: la suma de todos los números, de los pares y de los impares de la lista.reverse: devuelve una lista nueva con los números en orden inverso.largestysmallest: el número mayor y el menor.is_palindrome(word): si la palabra se lee igual de izquierda a derecha que de derecha a izquierda.sum_diagonalsysum_diagonals_once: la suma de las dos diagonales de una matriz cuadrada, contando el elemento central dos veces y una vez.- Todo junto: para la lista
[1, 2, 3, 4, 5], el número 7 (conis_primede la tarjeta anterior), las palabras «radar» y «ABCDE» y la matriz de 3 × 3 con los números del 1 al 9.
En Python, sum, max y min ya son funciones integradas. Si llamas sum a tu propia función, esta oculta la integrada en todo el programa. Por eso las nuestras se llaman total, largest y smallest.
Suma: 15, Pares: 6, Impares: 9Invertido: [5, 4, 3, 2, 1]Máx: 5, Mín: 17 es primo: Trueradar: True, ABCDE: FalseSuma con repetición: 30, Suma sin repetición: 25Test
Ponte a prueba
Lecciones relacionadas
Sección «Lecciones relacionadas»- Se basa en: Bucles · Listas · Arrays bidimensionales · Funciones
- Continúa en: Valores por defecto · Recursión · Clases y objetos · Constructores y self
- Ejercicios sobre el tema: Funciones