- Aprender
- Informática
- Programación
- Introducción a la programación con Python
- Funciones en Python
Funciones de Python
return. Descubre a qué variables puede acceder una función y cuáles puede modificar, describe tus funciones con cadenas de documentación (docstrings) y divide un programa en funciones pequeñas con nombres claros que construyas y pruebes una a una.PrincipianteUnidad 4 de 10 del curso Curso de Introducción a la programación con Python
Lo que aprenderás
- Escribe una función con
def, ejecútala mediante una llamada y sigue el orden en que Python ejecuta un programa que contiene funciones.- Define una función y llámalaEscribe la cabecera de una función y un cuerpo con sangría, elige un nombre claro y ejecuta la función llamándola con paréntesis.
- Sigue el flujo de ejecuciónSigue el orden en que Python ejecuta las sentencias cuando unas funciones llaman a otras y predice la salida de un programa a partir de ese orden.
- Define una función y llámala
- Usa parámetros y argumentos para dar a una función los valores con los que trabaja, asociados por posición, por nombre o mediante valores predeterminados.
- Usa parámetros y argumentos posicionalesAñade parámetros a la cabecera de una función, pasa los argumentos correspondientes en una llamada e interpreta los errores que produce un número incorrecto de argumentos.
- Llama a funciones con argumentos por palabra clavePasa argumentos por el nombre del parámetro, combina argumentos posicionales y por palabra clave en el orden correcto y corrige los errores que causan las combinaciones incorrectas.
- Asigna valores predeterminados a los parámetrosHaz que los parámetros sean opcionales mediante valores predeterminados, ordena correctamente los parámetros obligatorios y opcionales e identifica cuándo se crea un valor predeterminado.
- Usa parámetros y argumentos posicionales
- Usa
returnpara devolver un valor al código que llamó a una función, distingue entre devolver y mostrar, y escribe funciones cuyos resultados puedan guardarse, comprobarse y combinarse.- Devuelve un valor y úsaloTermina una función con
return, usa el valor devuelto en variables y expresiones y comprende por qué devolver un valor es distinto de mostrarlo. - Devuelve valores desde distintas rutas de ejecución y combina resultadosEscribe funciones con varias sentencias return, devuelve True o False, retorna de forma anticipada desde un bucle, devuelve dos valores y pasa el resultado de una función a otra.
- Devuelve un valor y úsalo
- Predice a qué variables puede acceder una función y cuáles puede modificar, pasa datos mediante parámetros y valores de retorno y usa
globalsolo cuando sea realmente necesario.- Trabaja con variables locales y parámetrosExplica por qué las variables creadas dentro de una función solo existen durante su llamada, cómo encuentra Python un nombre y por qué reasignar un parámetro no modifica la variable del código que realiza la llamada.
- Usa las variables globales con cuidadoLee valores globales de forma segura, comprende el error que causa asignar un valor a un nombre global, usa correctamente la sentencia
globaly da preferencia a los parámetros y valores de retorno.
- Trabaja con variables locales y parámetros
- Describe funciones con cadenas de documentación, divide un problema en funciones pequeñas con nombres claros y construye y comprueba un programa función por función.
- Documenta funciones con cadenas de documentaciónEscribe cadenas de documentación de una y varias líneas que sigan las convenciones habituales y consúltalas con
help(). - Descompón un problema en funcionesDescompón una tarea en pasos, convierte cada paso en una función con entradas y salidas claras y organiza el programa en torno a una función
main. - Construye y comprueba un programa función por funciónDesarrolla un programa en pasos pequeños, prueba cada función con entradas cuyos resultados conozcas y usa trazas de excepciones y salidas temporales para detectar errores de programación (bugs) dentro de las funciones.
- Documenta funciones con cadenas de documentación
Guía de estudio de Funciones en Python
1Define y llama a tus propias funciones
Una función da nombre a una parte útil del código para que puedas ejecutarla cuando necesites esa tarea. Escribir la definición y realizar una llamada son acciones distintas, y esa diferencia explica por qué algunos programas terminan sin mostrar nada. Escribirás definiciones con la sangría correcta, elegirás nombres legibles y seguirás la ejecución cuando una función llame a otra y después vuelva al código que la llamó.
1.1 Define una función y llámala
Una función es un bloque de código con nombre que realiza una tarea. Las funciones incorporadas como print() e input() ya te ofrecen tareas útiles que puedes llamar; def te permite crear las tuyas. Un buen nombre convierte varias líneas de trabajo en una llamada que indica qué quieres hacer.
Escribe la cabecera y el cuerpo
def greet():
print("Hello!")
print("Welcome to Python.")
greet()
greet()
La cabecera empieza con def, seguido del nombre, los paréntesis y los dos puntos. Las líneas con sangría forman el cuerpo. Usa cuatro espacios por cada nivel de sangría. Las líneas greet() sin sangría están fuera de la función, así que son llamadas del programa principal.
Cuando Python llega a la definición, crea la función y le da el nombre greet. Todavía no muestra ninguno de los mensajes. La primera llamada empieza en la primera línea del cuerpo y muestra «Hello!» seguido de «Welcome to Python.». La segunda vuelve a iniciar el cuerpo y muestra las mismas dos líneas. Hay cuatro líneas de salida en total.
Un nombre y una llamada son distintos
Los paréntesis de greet() lo convierten en una llamada, aunque esta función no necesite entradas. Una línea que solo contiene greet hace referencia a la función y no ejecuta nada. print(greet) muestra una descripción del objeto de función, incluida una dirección de memoria; no ejecuta el saludo.
Python debe haber ejecutado una definición antes de que una llamada use su nombre. Si un archivo empieza con greet() y define greet después, la primera línea lanza NameError: name 'greet' is not defined. Coloca la definición antes de la llamada del nivel superior.
Elige nombres que expliquen la tarea
Usa palabras en minúsculas unidas por guiones bajos, como print_receipt o convert_to_miles. Los nombres pueden contener letras, dígitos y guiones bajos, pero no pueden empezar por un dígito ni ser una palabra reservada como return. Los nombres distinguen entre mayúsculas y minúsculas: greet y Greet son nombres distintos.
Mantén disponibles los nombres incorporados. Después de input = "yes", el nombre input hace referencia a texto, así que input("Name? ") lanza TypeError: 'str' object is not callable. Llamar answer a la variable mantiene accesible la función incorporada.
Corrige primero la estructura
La ausencia de los dos puntos en la cabecera produce SyntaxError: expected ':'. Un cuerpo vacío o sin sangría produce un IndentationError. Una función que aún se está planificando necesita una sentencia; pass es un marcador provisional que no hace nada:
def print_receipt():
pass
print_receipt()
Este programa se ejecuta sin salida. La llamada llega a pass y después al final del cuerpo. Sustituye el marcador provisional por la tarea real cuando vayas a implementarla. Si una línea debía pertenecer al cuerpo pero se ejecuta en un momento incorrecto, comprueba su sangría antes de modificar la llamada.
Puntos clave
- Usa
def name():y un cuerpo con sangría para definir una función. - Una definición crea la función; los paréntesis forman una llamada que la ejecuta.
- Ejecuta la definición de una función antes de realizar una llamada que necesite su nombre.
- Elige nombres descriptivos en minúsculas con guiones bajos y evita los nombres incorporados.
- Usa
passcuando una función en preparación necesite un cuerpo provisional válido.
1.2 Sigue el flujo de ejecución
Un programa con funciones no ejecuta todos los cuerpos en el orden en que aparecen en la página. Una llamada cambia el flujo de ejecución: Python entra en la función llamada, termina su tarea y reanuda el código que la llamó justo después de esa llamada.
Sigue una llamada dentro de otra
def line():
print("----------")
def banner():
line()
print(" REPORT")
line()
print("Start")
banner()
print("End")
Primero, Python define line y banner. No se ejecuta ninguno de los cuerpos. La siguiente sentencia muestra «Start». La llamada a banner() entra en su cuerpo, cuya primera sentencia llama a line().
Python entra ahora en line, muestra «----------» y llega al final. Vuelve a la siguiente sentencia de banner, que muestra « REPORT». La segunda llamada a line() muestra otra línea de guiones. Por último, termina banner, así que el programa principal se reanuda y muestra «End».
La salida es:
Start
----------
REPORT
----------
End
Lleva un registro de las llamadas sin terminar
Mientras se ejecuta line, banner espera a que termine. El programa principal también espera a banner. Python registra estas llamadas sin terminar en la pila de llamadas. La llamada activa más interna termina primero, y cada código que realiza una llamada se reanuda en su siguiente sentencia.
Para seguir la ejecución en papel, numera las líneas del programa. Anota una línea del cuerpo solo cuando la ejecución llegue a ella mediante una llamada. En cada llamada, marca dónde se debe reanudar. Escribe la salida cuando se ejecute su print, conservando espacios y saltos de línea. Así separas la ruta que sigue el código de la salida que produce.
Define las funciones auxiliares antes de necesitarlas
La definición de una función auxiliar puede aparecer debajo de la definición de la función que la llama:
def show_report():
draw_line()
print("Ready")
def draw_line():
print("====")
show_report()
Esto funciona porque ambas definiciones se han ejecutado antes de que la llamada final entre en show_report. Python busca draw_line cuando el cuerpo la llama realmente. Mover show_report() por encima de def draw_line(): haría que la llamada fallara al intentar usar la función auxiliar aún no definida.
Las llamadas repetidas empiezan de nuevo
Una llamada dentro de un bucle entra en el cuerpo en cada repetición:
for i in range(3):
line()
Con la primera definición de line, esto muestra la línea de guiones tres veces. La función empieza en la primera sentencia de su cuerpo en cada llamada.
Si una llamada falla, Python muestra una traza de la excepción. Su última línea indica el tipo de error y el mensaje. Las entradas de llamadas anteriores van desde la llamada sin terminar más externa hasta la línea que falló. Leer primero el error final y después revisar la línea más interna y el código que la llamó te ayuda a localizar tanto la operación que falla como la ruta que le proporcionó los datos.
Puntos clave
- Sigue las sentencias del cuerpo en el orden de las llamadas y registra la salida cuando se ejecute cada
print. - La pila de llamadas registra las llamadas sin terminar y dónde se debe reanudar la ejecución.
- Una función auxiliar puede definirse debajo de la función que la llama si su definición se ejecuta antes de la llamada.
- Lee el error final de una traza de excepción y después revisa la línea que falla y el código que la llamó.
2Pasa información a las funciones
Los parámetros permiten que una función trabaje con distintas entradas sin reescribir su cuerpo. El código que realiza la llamada proporciona argumentos, y Python vincula esos valores con los nombres de los parámetros antes de iniciar el cuerpo. Asociarás argumentos por posición y por nombre, combinarás correctamente estas formas y elegirás valores predeterminados para los casos habituales. También verás por qué un valor predeterminado se crea al ejecutar la definición y cómo afecta eso a una lista usada como valor predeterminado.
2.1 Usa parámetros y argumentos posicionales
Una función puede reutilizarse con distintas entradas cuando su cabecera da nombre a los valores que necesita. Estos nombres son parámetros. El código que realiza la llamada proporciona argumentos, que son los valores concretos usados en una llamada determinada.
Asocia valores a nombres
def rectangle_area(width, height):
print("Area:", width * height)
rectangle_area(4, 2.5)
rectangle_area(3, 7)
Los parámetros son width y height. En la primera llamada, los argumentos son 4 y 2.5. Los argumentos posicionales se asocian de izquierda a derecha: width recibe 4 y height recibe 2,5. El cuerpo muestra «Area: 10.0». La siguiente llamada da valores nuevos a los mismos nombres de parámetros y muestra «Area: 21».
Cada parámetro actúa como una variable dentro de esa llamada. No necesitas asignar valores a width y height antes; la llamada los proporciona. Una función sin parámetros también necesita paréntesis vacíos tanto en su definición como en sus llamadas.
El orden puede cambiar el significado
def describe_pet(animal, name):
print(name, "is a", animal)
describe_pet("cat", "Milo")
describe_pet("Milo", "cat")
La primera llamada muestra «Milo is a cat». La segunda muestra «cat is a Milo». Ambas llamadas son válidas en Python, así que ningún error señala el cambio de significado. Lee el orden de la cabecera antes de elegir argumentos posicionales, sobre todo cuando varios parámetros aceptan el mismo tipo de valor.
Los argumentos pueden ser expresiones
Python evalúa cada expresión de argumento antes de iniciar el cuerpo. Con side = 6, la llamada rectangle_area(side, side) pasa 6 dos veces y muestra «Area: 36». El nombre de la variable del código que realiza la llamada no tiene que coincidir con ninguno de los nombres de los parámetros. La llamada rectangle_area(side + 1, 2) pasa 7 y 2; no pasa el texto «side + 1».
Interpreta un error en el número de argumentos
Cada parámetro sin valor predeterminado necesita un argumento. Con la función de área anterior:
| Llamada | Qué falla |
|---|---|
rectangle_area(4) | Falta height. |
rectangle_area(4, 2, 1) | Se proporcionaron tres argumentos para dos parámetros. |
La primera lanza TypeError: rectangle_area() missing 1 required positional argument: 'height'. La segunda lanza TypeError: rectangle_area() takes 2 positional arguments but 3 were given. Revisa la cabecera de la función indicada y después cuenta cómo la llamada ocupa sus parámetros.
Pasa el tipo de valor que necesita la tarea
Python no exige un tipo solo porque un parámetro se llame width. rectangle_area("4", 2) muestra «Area: 44» porque multiplicar texto por un entero repite ese texto. Como input() devuelve texto, convierte la entrada numérica antes de pasarla:
width = float(input("Width: "))
rectangle_area(width, 2)
Aquí, float() convierte el texto introducido en un número antes de que lo reciba la función de área.
Puntos clave
- Un parámetro es un nombre de la cabecera; un argumento es un valor proporcionado por una llamada.
- Los argumentos posicionales ocupan los parámetros de izquierda a derecha.
- Python evalúa las expresiones de los argumentos antes de ejecutar el cuerpo de la función.
- Cada parámetro obligatorio necesita un valor; la falta o el exceso de argumentos lanza
TypeError. - Convierte la entrada numérica de texto a número antes de pasarla a un cálculo.
2.2 Llama a funciones con argumentos por palabra clave
Un argumento por palabra clave nombra en la llamada su parámetro de destino. Esto facilita la lectura de una llamada cuando varios valores podrían confundirse. Python asocia la palabra clave con el nombre de la cabecera en lugar de usar su posición.
Asocia por nombre
def describe_pet(animal, name):
print(name, "is a", animal)
describe_pet(name="Milo", animal="cat")
describe_pet(animal="cat", name="Milo")
Ambas llamadas muestran «Milo is a cat». El orden de los argumentos por palabra clave puede cambiar porque cada valor indica el parámetro que ocupa. La misma idea hace que rectangle_area(width=4, height=2.5) sea legible sin comprobar qué dimensión iba primero.
Una palabra clave no es una variable nueva en el código que realiza la llamada. En describe_pet(name="Milo", animal="cat"), name= dirige «Milo» al parámetro. No asigna «Milo» a una variable del nivel superior llamada name. Escribe los argumentos por palabra clave sin espacios alrededor de =, siguiendo el estilo habitual de Python.
Combina argumentos posicionales y por palabra clave
describe_pet("cat", name="Milo")
El primer argumento ocupa animal por posición. La palabra clave ocupa name, así que cada parámetro recibe exactamente un valor. Los argumentos posicionales deben ir primero. La llamada describe_pet(name="Milo", "cat") se rechaza con SyntaxError: positional argument follows keyword argument.
Para revisar una llamada combinada, ocupa las posiciones de izquierda a derecha y después asocia las palabras clave. Comprueba que ninguna posición se ocupe dos veces y que no quede vacía ninguna obligatoria.
Corrige las palabras clave duplicadas o desconocidas
| Llamada | Diagnóstico |
|---|---|
describe_pet("cat", animal="dog") | animal recibe tanto «cat» como «dog». |
describe_pet(animal="cat", nmae="Milo") | La cabecera no tiene ningún parámetro llamado nmae. |
El duplicado lanza TypeError: describe_pet() got multiple values for argument 'animal'. El nombre mal escrito lanza TypeError: describe_pet() got an unexpected keyword argument 'nmae'. Compara los nombres carácter a carácter; las mayúsculas y minúsculas también importan. Cambiar el orden de los argumentos no corrige una asignación duplicada a un parámetro.
Reconoce las palabras clave en las funciones incorporadas
print("a", "b", "c", sep="-")
print("Loading", end="...")
print("done")
La primera línea muestra «a-b-c». sep proporciona el texto situado entre los valores mostrados. Las dos llamadas siguientes producen «Loading...done» en una línea: end sustituye el salto de línea habitual después de «Loading».
Algunas funciones incorporadas también aceptan argumentos por nombre; por ejemplo, round(3.14159, ndigits=2) da 3,14. Usa los nombres de parámetros documentados para la función que llamas. Una palabra descriptiva que inventes no se reconoce solo porque parezca adecuada para la tarea.
Puntos clave
- Los argumentos por palabra clave se asocian con los nombres de los parámetros, así que su orden puede variar.
- Coloca los argumentos posicionales antes de los argumentos por palabra clave.
- Ocupa cada parámetro exactamente una vez y escribe cada palabra clave con exactitud.
- Una palabra clave en una llamada dirige un valor; no asigna una variable del código que realiza la llamada.
- En
print,sepcontrola los separadores yendcontrola la terminación.
2.3 Asigna valores predeterminados a los parámetros
Un valor predeterminado permite que una llamada omita un argumento cuando una elección habitual resulta adecuada. Escribe el valor predeterminado junto a su parámetro en la cabecera. Proporcionar un argumento sustituye el valor predeterminado para esa llamada.
Haz que un parámetro sea opcional
def greet(name, greeting="Hello"):
print(greeting + ",", name + "!")
greet("Ana")
greet("Ana", "Welcome")
greet("Ana", greeting="Hi")
La salida es «Hello, Ana!», «Welcome, Ana!» y «Hi, Ana!». name es obligatorio porque no tiene un valor predeterminado. Por tanto, greet() lanza un TypeError, aunque el otro parámetro sea opcional.
En estas cabeceras, los parámetros obligatorios van antes de los que tienen valores predeterminados. def greet(greeting="Hello", name): no es válido. Python informa de un error de sintaxis porque un parámetro sin valor predeterminado aparece después de uno que sí lo tiene. Mueve name antes de greeting para mantenerlo como obligatorio.
Cambia una opción
def order_coffee(size, shots=1, milk="none"):
print(size, "coffee,", shots, "shot(s), milk:", milk)
order_coffee("large", milk="oat")
Esto muestra «large coffee, 1 shot(s), milk: oat». La palabra clave llega a milk mientras shots conserva 1. Una llamada posicional como order_coffee("medium", 2) modifica shots y deja milk en «none». La asociación posicional no se salta un parámetro opcional para llegar al siguiente.
Las funciones incorporadas también ofrecen valores predeterminados: una llamada normal a print() separa los valores con un espacio y termina con un salto de línea. round(3.7) da el número entero 4; round(3.14159, 2) solicita dos decimales y da 3,14.
Los valores predeterminados se crean al ejecutar la definición
rate = 0.05
def price_with_tax(price, tax_rate=rate):
return price * (1 + tax_rate)
rate = 0.08
print(price_with_tax(100))
print(price_with_tax(100, rate))
El valor predeterminado guarda 0,05 cuando se ejecuta def. Cambiar rate después no modifica ese valor guardado. Las llamadas muestran «105.0» y «108.0»: solo la segunda proporciona explícitamente la nueva tasa.
Evita compartir una lista por accidente
Una lista contiene elementos, y append añade un elemento a esa misma lista. Con una lista como valor predeterminado, todas las llamadas que omiten el argumento la comparten:
def add_item(item, basket=[]):
basket.append(item)
print(basket)
add_item("apple")
add_item("pear")
Esto muestra ['apple'] y después ['apple', 'pear']. La lista predeterminada se creó una vez, no una vez por llamada. Para crear una lista nueva cada vez que se omita el argumento, usa None como señal:
def add_item(item, basket=None):
if basket is None:
basket = []
basket.append(item)
print(basket)
Ahora esas dos llamadas muestran ['apple'] y ['pear']. Una lista proporcionada explícitamente sigue usándose tal como se recibe. Describe los parámetros opcionales y sus valores predeterminados en la cadena de documentación para que quienes llamen a la función sepan qué valores se eligen al omitirlos.
Puntos clave
- Un argumento opcional omitido usa su valor predeterminado; un argumento explícito lo sustituye.
- Coloca los parámetros obligatorios antes de los que tienen valores predeterminados.
- Usa una palabra clave para cambiar una opción posterior sin ocupar las posiciones opcionales anteriores.
- Las expresiones de los valores predeterminados se evalúan una vez al ejecutar
def. - Una lista mutable como valor predeterminado se comparte entre las llamadas que omiten el argumento.
- Usa
Noney crea una lista en el cuerpo cuando cada argumento omitido necesite una lista nueva.
3Devuelve resultados mediante valores de retorno
Un cálculo resulta más útil cuando su resultado puede alimentar otro cálculo, una condición o una salida en pantalla. La sentencia return lo hace posible al devolver un valor al código que realiza la llamada. Distinguirás entre devolver y mostrar, seguirás el primer return que se ejecute y comprobarás las rutas que podrían terminar sin un resultado útil. Después crearás funciones booleanas, terminarás búsquedas correctamente y combinarás los resultados de funciones pequeñas.
3.1 Devuelve un valor y úsalo
Una función puede dar al código que la llama un resultado que pueda usar. La sentencia return termina la llamada y devuelve su valor. En el punto de llamada, la llamada representa ese valor devuelto.
Guarda y combina resultados
def rectangle_area(width, height):
return width * height
area = rectangle_area(4, 2.5)
print(area)
print(rectangle_area(3, 4) + rectangle_area(2, 5))
La primera llamada devuelve 10,0, que se asigna a area; el primer print lo muestra. En la última línea, las dos llamadas devuelven 12 y 10. Python suma esos resultados y muestra «22». La propia función no contiene ningún print, así que puede proporcionar tanto un resultado que se guarde como una parte de un cálculo mayor.
Un valor devuelto también puede comprobarse en una condición o pasarse a otra función. Esto separa la tarea de calcular de la decisión del código que realiza la llamada sobre cómo usar la respuesta.
Mostrar y devolver tienen tareas distintas
def double_print(n):
print(n * 2)
result = double_print(5)
print(result)
La llamada muestra «10», pero ese número mostrado no se devuelve como resultado. double_print llega al final de su cuerpo, así que devuelve None. Por eso la última línea muestra «None».
| Operación | Adónde va el valor |
|---|---|
print(value) | Lo muestra para que una persona lo lea. |
return value | Lo envía al código que realiza la llamada para que el programa lo use. |
double_print(5) + 1 primero muestra «10» y después lanza TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'. Sustituye el cuerpo por return n * 2 cuando el código que realiza la llamada necesite el doble del número. Una función destinada solo a producir un efecto, como mostrar un mensaje, puede devolver None de forma adecuada; estas funciones se denominan a veces funciones sin valor de retorno útil. Una función que devuelve un resultado útil se denomina a veces función con valor de retorno útil.
Detente en el primer return ejecutado
def to_fahrenheit(celsius):
return celsius * 9 / 5 + 32
print("Converted")
print(to_fahrenheit(20))
Esto muestra «68.0». Nunca se llega al print del cuerpo porque return ya ha terminado la llamada. Elimina esa sentencia inalcanzable o mueve una acción necesaria antes del retorno. La conversión devuelve números de coma flotante porque / produce un número de coma flotante. Las entradas 100 y -40 dan 212,0 y -40,0.
Un return sin expresión también termina una llamada y devuelve None. Toda llamada a función tiene un resultado, aunque no se haya proporcionado un valor útil.
Haz visibles los resultados en un archivo de programa
Una llamada aislada a rectangle_area(3, 4) calcula 12 y después descarta el resultado sin usar en un archivo. Usa print(rectangle_area(3, 4)) para mostrarlo o asígnalo a una variable. La consola interactiva muestra los resultados de las expresiones salvo None, así que una prueba correcta en la consola puede parecer distinta de ejecutar la misma línea en un archivo.
Puntos clave
return valuetermina la llamada y hace que esta represente ese valor.- Mostrar presenta un valor en pantalla; devolver lo pone a disposición del código que realiza la llamada.
- Llegar al final del cuerpo o usar un
returnsin valor devuelveNone. - Las sentencias posteriores a un return ejecutado no se ejecutan en esa llamada.
- Usa un resultado devuelto guardándolo, mostrándolo, comprobándolo o combinándolo.
3.2 Devuelve valores desde distintas rutas de ejecución y combina resultados
Distintas entradas pueden necesitar distintas respuestas. Una función puede tener varias sentencias return, pero una llamada se detiene en la primera que ejecuta. Sigue la ruta real a través de sus ramas y bucles para encontrar el resultado.
Ordena las comprobaciones que se solapan
def letter_grade(score):
if score >= 90:
return "A"
if score >= 80:
return "B"
if score >= 70:
return "C"
return "F"
Para 85, la primera condición es falsa y la segunda es verdadera. La función devuelve «B» sin comprobar las condiciones restantes. Para 42, las tres condiciones son falsas, así que el return final proporciona «F». Las sentencias if independientes funcionan porque cada rama cuya condición se cumple termina la llamada.
Aquí debe comprobarse primero el umbral más alto. Si score >= 70 fuera primero, una puntuación de 95 devolvería «C». Con rangos que se solapan, una coincidencia amplia al principio puede ocultar una respuesta posterior más específica.
Cubre la ruta sin ninguna rama coincidente
def sign(n):
if n > 0:
return "positive"
elif n < 0:
return "negative"
return "zero"
La última línea cubre el cero. Sin ella, sign(0) llegaría al final y devolvería None. Sigue una entrada de cada rama y de cualquier caso restante; probar solo entradas positivas y negativas no detectaría este vacío.
Devuelve una comparación booleana
def is_even(n):
return n % 2 == 0
if is_even(10):
print("Even")
La comparación ya produce True o False. is_even(10) devuelve True, mientras que is_even(7) devuelve False. Usa el resultado directamente en una condición. Añadir == True no mejora la comprobación.
Termina la búsqueda antes de informar de que no hay coincidencias
def smallest_divisor(n):
for d in range(2, n):
if n % d == 0:
return d
return n
Para 91, los candidatos del 2 al 6 fallan y después el 7 lo divide exactamente. Devolver 7 termina tanto el bucle como la función. Para 13, el bucle no encuentra ningún divisor, así que el return final da 13.
Una prueba de primalidad debe permitir que la búsqueda continúe después de un candidato que no sirve:
def is_prime(n):
if n < 2:
return False
for d in range(2, n):
if n % d == 0:
return False
return True
El True final está fuera del bucle. Colocarlo en un else dentro del bucle devolvería un valor después de comprobar solo el primer candidato: el 9 se aceptaría erróneamente porque no es divisible por 2. Con la función corregida, 9 y 1 devuelven False; 2, 7 y 97 devuelven True. Para 2, el bucle no tiene candidatos y la ejecución llega al True final.
Devuelve dos valores
def share(total, people):
return total // people, total % people
each, left = share(17, 5)
print(each, left)
La llamada devuelve una tupla, un resultado agrupado que contiene 3 y 2. La asignación lo desempaqueta en dos nombres, así que la salida es «3 2». Mostrar la llamada directamente produciría «(3, 2)». El número de nombres debe coincidir con el número de valores que se desempaquetan.
Combina llamadas de dentro hacia fuera
def add(a, b):
return a + b
def to_fahrenheit(celsius):
return celsius * 9 / 5 + 32
print(to_fahrenheit(add(10, 15)))
add devuelve primero 25. Ese valor se convierte en el argumento de to_fahrenheit, que devuelve 77,0. Por último, print muestra «77.0». Cada llamada interna debe devolver el valor que necesita la siguiente función.
Puntos clave
- El primer return ejecutado termina una llamada, así que ordena con cuidado las comprobaciones que se solapan.
- Incluye un resultado útil para cada ruta de entrada que deba gestionar la función.
- Una función booleana puede devolver directamente una comparación.
- Dentro de un bucle de búsqueda, devuelve el resultado encontrado; informa de que no hay coincidencias cuando fallen todos los candidatos.
- Los valores devueltos separados por comas forman una tupla que puede desempaquetarse.
- En las llamadas anidadas, el resultado interno se convierte en el argumento de la llamada externa.
4Identifica dónde se pueden usar las variables: ámbito local y global
Un nombre dentro de una función puede parecer idéntico a otro de fuera y, aun así, hacer referencia a una variable distinta. El ámbito indica dónde puede usarse un nombre, y la asignación ayuda a determinar a cuál se refiere Python. Seguirás los parámetros y otras variables locales durante una llamada, distinguirás entre reasignar y modificar una lista compartida, y leerás ajustes globales. También corregirás un error habitual de ámbito y harás explícitos los cambios de valores en las llamadas.
4.1 Trabaja con variables locales y parámetros
El ámbito describe dónde puede usarse un nombre. Los parámetros y los nombres a los que se asignan valores dentro de una función son locales a la llamada de esa función. El código que realiza la llamada y una función pueden usar nombres similares sin compartir las mismas variables locales.
Mantén los nombres locales dentro de su llamada
def make_greeting():
message = "Hi"
print(message)
make_greeting()
Esto muestra «Hi». Añadir print(message) después de la llamada lanza NameError: name 'message' is not defined: el nombre local no está disponible allí. Para poner el valor a disposición del código que realiza la llamada, devuélvelo y guárdalo:
def make_greeting():
return "Hi"
message = make_greeting()
print(message)
El message del nivel superior es una variable nueva del código que realiza la llamada y recibe el valor devuelto. La función no hace visibles fuera sus propios nombres locales.
Cada llamada recibe variables locales nuevas. Si un cuerpo establece count = 0, suma 1 y lo muestra, dos llamadas muestran «1» y «1». La segunda no continúa con el contador de la primera. Distintas funciones también pueden usar nombres locales como total de forma independiente.
Sigue la ocultación y la búsqueda de nombres
x = 10
def show():
x = 5
print(x)
show()
print(x)
La salida es «5» y después «10». La x local oculta la x global dentro de show; la asignación no modifica el valor del nivel superior. Una variable global pertenece al ámbito del nivel superior del archivo. Las asignaciones ordinarias fuera de las funciones crean variables globales.
Para una función definida en el nivel superior del archivo, Python busca un nombre entre sus nombres locales, después entre los globales del archivo y, por último, entre los incorporados, como print. Se usa la primera coincidencia. Por tanto, los nombres locales y globales son lugares distintos que revisar cuando un valor parece incorrecto.
Reasignar un parámetro no modifica el nombre del código que realiza la llamada
def add_bonus(points):
points = points + 10
print(points)
score = 50
add_bonus(score)
print(score)
points empieza con el valor 50. Su reasignación local lo convierte en 60, así que la primera salida es «60». El score del código que realiza la llamada sigue valiendo 50. Para actualizar ese nombre explícitamente, usa una función que devuelva points + 10 y después escribe score = add_bonus(score).
Modificar una lista es una operación distinta
Una lista puede compartirse mediante dos nombres:
def add_guest(guests, name):
guests.append(name)
party = ["Ana"]
add_guest(party, "Ben")
print(party)
El parámetro guests y la variable party del código que realiza la llamada hacen referencia a la misma lista. append modifica su contenido, así que la salida es «['Ana', 'Ben']». En cambio, asignar guests = [] dentro de la función haría que solo el nombre local apuntara a una lista nueva; party seguiría haciendo referencia a la original. Al seguir un argumento de tipo lista, pregúntate si la línea modifica el objeto compartido o solo reasigna un nombre local.
Puntos clave
- Los parámetros y los nombres a los que se asignan valores dentro de una función son locales a su llamada.
- Cada llamada recibe variables locales nuevas; los valores de retorno llevan los resultados al exterior.
- Un nombre local puede ocultar uno global sin modificar el valor global.
- Reasignar un parámetro deja intacta la variable del código que realiza la llamada.
- Modificar una lista compartida cambia la lista que ve el código que realiza la llamada.
4.2 Usa las variables globales con cuidado
Una función puede leer un nombre global sin una declaración. Asignar un valor a un nombre en su cuerpo sigue una regla distinta, y confundir estas operaciones es una causa habitual de UnboundLocalError.
Lee un ajuste fijo
TAX_RATE = 0.25
def tax(amount):
return amount * TAX_RATE
print(tax(80))
La salida es «20.0». amount es local; TAX_RATE se lee de las variables globales del archivo. Las mayúsculas identifican una constante por convención e indican que el programa debe mantener fijo el ajuste. Python no impone esa convención.
La asignación convierte un nombre en local en todo el cuerpo
total = 0
def add_to_total(amount):
total = total + amount
add_to_total(5)
La asignación convierte total en local en toda add_to_total. Para calcular el lado derecho, Python intenta leer ese nombre local antes de que tenga un valor. No recurre al total global. La llamada lanza UnboundLocalError: cannot access local variable 'total' where it is not associated with a value.
La decisión se basa en todo el cuerpo, no solo en las líneas ya ejecutadas. Un cuerpo con print(count) seguido de count = 10 también trata count como local en la línea que lo muestra. Un count global no puede proporcionar el valor local que falta.
Declara una asignación global deliberada
total = 0
def add_to_total(amount):
global total
total = total + amount
add_to_total(5)
add_to_total(7)
print(total)
Ahora tanto la lectura como la asignación hacen referencia al nombre global, así que la salida es «12». Coloca global total antes de cualquier uso de total en la función. Usar el nombre antes de su declaración es un error de sintaxis.
Una declaración por sí sola no crea un valor. Una asignación posterior puede crear una variable global que no existía: el cuerpo de una función que contenga global level y después level = 1 crea el level global cuando se llama a la función.
Muestra el cambio mediante entradas y un resultado
La misma suma acumulada puede escribirse con una interfaz explícita:
def add_to_total(total, amount):
return total + amount
total = 0
total = add_to_total(total, 5)
total = add_to_total(total, 7)
print(total)
Esto también muestra «12». Cada llamada muestra el valor anterior que se pasa, y la asignación muestra adónde va el nuevo. Puedes comprobar add_to_total(10, 3) por separado sin preparar antes un estado global oculto. Si varias funciones modifican la misma variable global, su comportamiento depende del orden en que se ejecutan.
| Operación dentro de una función | ¿Se necesita una declaración? |
|---|---|
| Leer un ajuste global | No. |
| Reasignar un nombre global | global name antes de usarlo. |
| Añadir al final de una lista global existente | No; el nombre no se reasigna. |
Leer una lista compartida y modificar su contenido usa la referencia existente. Sustituir el valor de ese nombre global por una lista distinta es una asignación, así que se aplica la regla de asignación.
Puntos clave
- Lee un nombre global sin una declaración especial.
- Una asignación en cualquier parte de una función convierte ese nombre en local salvo que se declare global.
- Leer una variable local sin un valor asignado lanza
UnboundLocalError. - Coloca
global nameantes de usar un nombre que la función reasigne deliberadamente en el ámbito global. - Da preferencia a los parámetros y valores de retorno cuando un valor cambiante pueda pasarse explícitamente.
- Modificar una lista y reasignar su nombre siguen reglas distintas.
5Documenta y diseña programas con funciones
Las buenas funciones necesitan tareas claras además de código correcto. Quien llama a una función debe poder saber qué necesita, qué devuelve y qué efectos produce sin estudiar cada línea de su cuerpo. Escribirás cadenas de documentación, dividirás un programa completo en funciones auxiliares y las conectarás mediante una función principal pequeña. Después comprobarás cada parte por separado con resultados esperados, entradas límite y las pistas de una traza de excepción.
5.1 Documenta funciones con cadenas de documentación
Quien llama a una función necesita conocer su tarea sin leer toda su implementación. Una cadena de documentación proporciona esa descripción. Python reconoce una cadena como la cadena de documentación de la función cuando es la primera sentencia del cuerpo.
Escribe primero una descripción breve
def to_fahrenheit(celsius):
"""Convert a temperature from degrees Celsius to degrees Fahrenheit."""
return celsius * 9 / 5 + 32
print(to_fahrenheit.__doc__)
La salida es la frase que está entre las comillas. Python guarda la cadena de documentación en __doc__; las comillas triples no forman parte de la frase guardada. help(to_fahrenheit) muestra la descripción junto con la firma to_fahrenheit(celsius). Pasa el nombre de la función a help, sin llamar a la función.
La convención habitual es usar comillas dobles triples, incluso para una cadena de documentación de una línea. Empieza con una orden como «Devuelve el área de un rectángulo.» y termina con un punto. Mantén una descripción breve y sus comillas de cierre en una sola línea. No necesitas repetir el nombre de la función ni la lista de parámetros porque la ayuda ya los incluye.
Añade detalles cuando sean necesarios para llamar a la función
def split_bill(total, people, tip_rate=0.2):
"""Return each person's share of a bill, including the tip.
total: the bill before the tip
people: the number of people sharing the bill
tip_rate: the tip as a fraction of the bill (default 0.2)
"""
return total * (1 + tip_rate) / people
La primera línea indica el resultado. Una línea en blanco la separa de los detalles sobre las entradas. El valor predeterminado se documenta como 0,2, una fracción de la cuenta; esto evita que quien llama a la función use 20 como valor para una propina del 20 %. Las comillas de cierre de una cadena de documentación de varias líneas van en una línea aparte.
Para split_bill(84, 4), la función aplica la propina predeterminada y devuelve 25,2. Quien la llama puede conocer el significado de las tres entradas antes de elegir los argumentos. Incluye las unidades cuando sean relevantes y describe efectos como mostrar algo, para que se puedan predecir tanto el resultado como el comportamiento visible.
Distingue la documentación de los comentarios
| Forma | Finalidad principal |
|---|---|
| Primera cadena del cuerpo | Describe la función para quien la llama y aparece en help. |
Comentario con # en el cuerpo | Explica un detalle del código a quien lee la implementación. |
Una cadena situada después de una asignación u otra sentencia del cuerpo no es la cadena de documentación de la función. Es una expresión de cadena sin usar, y __doc__ es None si no hay una cadena de documentación como primera sentencia. Un comentario con # tampoco se convierte en la descripción de la ayuda.
Escribe el resumen mientras decides la tarea de la función. Si la frase necesita varias acciones sin relación entre sí, reconsidera si conviene dividir la función. Cuando cambies parámetros, valores predeterminados, valores devueltos o efectos en pantalla, actualiza la cadena de documentación al mismo tiempo; quienes llaman a la función confían en ella como parte de la interfaz.
Puntos clave
- La cadena de documentación de una función es la primera sentencia de su cuerpo.
- Usa comillas dobles triples y una frase imperativa breve terminada en punto.
- En las descripciones más largas, separa el resumen de los detalles con una línea en blanco.
- Describe las entradas relevantes, las unidades, los valores predeterminados, los resultados y los efectos.
- Consulta la documentación guardada con
help(name)oname.__doc__.
5.2 Descompón un problema en funciones
La descomposición consiste en dividir una tarea en tareas más pequeñas. Cada función se responsabiliza de una tarea, con entradas claras y un resultado o efecto claro. Así, el programa principal puede leerse como una secuencia breve de pasos con nombre.
Planifica los datos antes de escribir los cuerpos
Para un programa que informa de la media de unas puntuaciones de pruebas y de una calificación con letra, identifica tres tipos de trabajo: leer puntuaciones, calcular una media y elegir una calificación. Decide qué recibe y devuelve cada función auxiliar. Deja la salida en pantalla en main, donde se reúnen los resultados.
def get_score(prompt):
return float(input(prompt))
def average(a, b, c):
return (a + b + c) / 3
def letter_grade(score):
if score >= 90:
return "A"
if score >= 80:
return "B"
if score >= 70:
return "C"
return "F"
def main():
first = get_score("Test 1: ")
second = get_score("Test 2: ")
third = get_score("Test 3: ")
avg = average(first, second, third)
print("Average:", round(avg, 1), "Grade:", letter_grade(avg))
main()
Con las puntuaciones 78, 92 y 85, average devuelve 85,0. Ese resultado se convierte en el argumento de letter_grade, que devuelve «B». La salida en pantalla es «Average: 85.0 Grade: B».
main coordina la secuencia; no necesita saber cómo elige letter_grade su respuesta. Usar una función mediante su tarea e interfaz, sin seguir cada sentencia de su cuerpo, es abstracción procedimental. Ya usas print de esta forma.
Ofrece una interfaz clara al código que realiza la llamada
La interfaz de una función consta de su nombre, sus parámetros, el resultado devuelto y su comportamiento documentado. average(a, b, c) necesita tres números y devuelve su media. El código que la llama no tiene que leer una solicitud de datos ni capturar texto mostrado para obtener ese número. Puedes reescribir el cálculo manteniendo las entradas y la salida acordadas, y las llamadas existentes seguirán funcionando.
Usa nombres como calculate_total y print_receipt para acciones, e is_even o has_discount para preguntas booleanas. Los nombres de parámetros como price y quantity explican qué valores corresponden a cada posición. Los nombres de una sola letra pueden ser adecuados cuando su significado está claro, como en las tres entradas de average.
Convierte la repetición en parámetros
Si varias partes de un programa muestran títulos distintos entre las mismas líneas de signos igual, convierte el título en un parámetro de print_heading(title). La estructura repetida pertenece a un solo cuerpo, mientras que el texto variable pertenece a las llamadas. Así, un cambio posterior en la longitud de la línea solo necesita una modificación.
Elige cómo dividir las funciones para que las tareas sean más fáciles de entender o reutilizar. Colocar todas las sentencias en una única main larga oculta las tareas más pequeñas. Convertir cada expresión trivial en una función auxiliar usada una sola vez puede añadir nombres sin mejorar la legibilidad. Una comprobación útil es ver si una frase breve puede describir cada tarea y sus entradas y salidas.
Termina el archivo con la llamada real a main() después de todas las definiciones. Un programa que solo contiene definiciones creará sus funciones y terminará sin ejecutar sus cuerpos.
Puntos clave
- Descompón la tarea en tareas más pequeñas con entradas y salidas identificadas.
- Separa los cálculos de la entrada de datos y la salida en pantalla cuando deban reutilizarse o comprobarse.
- Haz que
maincoordine las funciones auxiliares y llama amain()después de las definiciones. - Usa parámetros para las partes que varían en el código repetido.
- Una interfaz estable permite llamar a una función sin depender de su cuerpo.
- Elige cómo dividir las funciones para que el programa sea más fácil de entender.
5.3 Construye y comprueba un programa función por función
Crear varias funciones antes de ejecutar alguna dificulta localizar un fallo. El desarrollo incremental consiste en escribir una parte pequeña, comprobarla y después añadir la siguiente. Mantienes un programa que funciona y reduces la cantidad de código nuevo que debes revisar.
Usa un esbozo de función durante la planificación
Un esbozo de función tiene la cabecera prevista y un cuerpo provisional. Una cadena de documentación y pass mantienen válida la definición, pero la función devuelve None hasta que la implementes. Un retorno fijo puede ayudar a probar la salida en pantalla del código que la llama sin dar por hecho que el cálculo real ya funciona.
Empieza con una función auxiliar de cálculo cuyo resultado puedas obtener de forma independiente. Una vez que se comporte correctamente, conéctala con la siguiente. Deja la entrada interactiva para cuando los cálculos puedan comprobarse con llamadas directas.
Decide los resultados esperados antes de ejecutar
Con las funciones average y letter_grade, las puntuaciones 70, 75 y 72 tienen una media aproximada de 72,33, así que su calificación esperada es «C». Comprueba ambas etapas:
print(average(70, 75, 72))
print(letter_grade(average(70, 75, 72)) == "C")
Las salidas son «72.33333333333333» y «True». La comparación comprueba directamente la calificación esperada; mirar solo la salida del propio programa sin una expectativa independiente puede hacer que una respuesta errónea pero plausible pase inadvertida.
Prueba los límites además de las entradas habituales
Para un umbral de 90, prueba 90 y 89,9. La función de calificación correcta devuelve «A» y «B». Si su primera condición fuera score > 90, solo la comprobación del límite exacto revelaría que 90 pasa erróneamente a la siguiente condición.
Incluye un valor habitual, límites exactos, valores cercanos y entradas extremas que la función deba gestionar. En la función de calificación, comprobar 70 y 0 recorre el límite mínimo para aprobar y la ruta final de «F». Una comprobación como print(letter_grade(85) == "B") es sencilla porque la función recibe un valor y devuelve su resultado.
Lee la traza de la excepción y revisa el valor recibido
Supón que main llama a letter_grade(input("Score: ")). Introducir «85» envía una cadena a una comparación con un número. El error final es TypeError: '>=' not supported between instances of 'str' and 'int'. La traza señala la comparación dentro de la función auxiliar, mientras que una línea de llamada anterior señala main.
El fallo se produce en la comparación, pero la corrección corresponde al lugar donde se prepara la entrada: conviértela con float() antes de pasarla. Un print("letter_grade got", score) temporal como primera línea ayuda a revelar una entrada inesperada. Si su tipo no está claro, revisa el código que realiza la llamada y la conversión que usa. Elimina las salidas de depuración después de corregir el error.
Relaciona los síntomas con las causas probables
| Síntoma | Qué revisar |
|---|---|
Un resultado es None | Un retorno que falta o una ruta sin cubrir. |
| No aparece ningún efecto | Una llamada que falta o un resultado devuelto sin usar. |
| Un resultado plausible tiene un significado incorrecto | Argumentos intercambiados. |
NameError | Un nombre de función o variable mal escrito o no disponible. |
Después de corregir una función auxiliar, vuelve a ejecutar las comprobaciones que recorran las rutas afectadas y el código que la llama para conectarla con el programa.
Puntos clave
- Construye y comprueba una función antes de añadir la siguiente.
- Obtén los resultados esperados de forma independiente antes de compararlos con las llamadas.
- Prueba los límites exactos y los valores cercanos para detectar errores en las comparaciones.
- Usa la traza de la excepción para localizar el fallo y el código que realiza las llamadas.
- Elimina las salidas de depuración temporales una vez corregido el problema.
Ejemplos de Funciones en Python
1Escribe una función y sigue sus llamadas
10 pasos
- 1IntroducciónDa nombre a una tarea
Una función te permite escribir una tarea útil una vez y elegir cuándo ejecutarla. Empezarás con un saludo y después seguirás un informe que llama a una función auxiliar.
Al leer, distingue dos preguntas: «¿Ha creado Python esta función?» y «¿La ha llamado ya el programa?». La primera hace que el nombre esté disponible; la segunda inicia el trabajo del cuerpo. Esta distinción explica por qué un archivo lleno de definiciones puede terminar sin salida.
- 2ExplicaciónEscribe el cuerpo reutilizable
def greet(): print("Hello!") print("Welcome to Python.")La cabecera usa
def, un nombre, paréntesis y dos puntos. Las dos líneas con sangría de cuatro espacios forman el cuerpo. Python crea la función al ejecutar esta definición, pero todavía no se ejecuta ninguno de los print.La siguiente sentencia sin sangría estará fuera de la función. La sangría indica a Python dónde termina esta tarea; forma parte de la estructura del programa.
- 3EjemploEjecútala dos veces
Añade estas líneas después de la definición:
greet() greet()La primera llamada entra en el cuerpo y muestra «Hello!» seguido de «Welcome to Python.». La segunda vuelve a empezar en la primera línea del cuerpo y muestra ambos mensajes de nuevo. Hay cuatro líneas de salida.
Los paréntesis vacíos siguen siendo importantes:
greetpor sí solo hace referencia al objeto de función. No lo llama, yprint(greet)muestra una descripción de la función en lugar del saludo. - 4DesafíoPredice qué ocurre si falta una llamada
¿Qué muestra este archivo?
def ready(): print("Ready") ready print("Waiting")---reveal---
Solo muestra «Waiting». La definición crea
ready, y el nombre por sí solo hace referencia a esa función sin ejecutarla. Para mostrar también el mensaje, cambiareadyporready(). La llamada se ejecutaría entonces antes del print final y produciría «Ready» y «Waiting» en líneas separadas. - 5ConsejoMantén utilizables los nombres y los cuerpos
Usa nombres como
print_receipt: palabras en minúsculas unidas por guiones bajos que describen la tarea. Evita sustituir un nombre incorporado. Asignar texto ainputoculta la función, así que uninput(...)posterior intenta llamar al texto y falla.Un cuerpo sin terminar necesita una sentencia. Usa un
passcon sangría como marcador provisional. Un comentario por sí solo no es un cuerpo, y unpasssin sangría quedaría fuera de la función. - 6EjemploEntra en una función que realiza una llamada
def line(): print("----------") def banner(): line() print(" REPORT") line() print("Start") banner() print("End")Primero se ejecutan ambas definiciones sin mostrar nada. La sentencia del nivel superior muestra «Start» y después
banner()entra en el cuerpo de banner. Su primera línea llama aline, así que banner debe esperar mientras esa función auxiliar muestra sus guiones. No avances hasta el título antes de que termine la función auxiliar. - 7ExplicaciónReanuda la ejecución un nivel cada vez
Cuando termina
line, la ejecución se reanuda en el print del título dentro debanner. Después, banner llama alinepor segunda vez y produce la segunda línea de guiones. Cuando termina banner, el programa principal se reanuda y muestra «End».La pila de llamadas de Python registra las llamadas sin terminar y sus puntos de retorno. Mientras se ejecuta la función auxiliar, banner y el programa principal esperan. Un seguimiento en papel puede marcar estos puntos de retorno y registrar la salida cuando se ejecute realmente cada print.
- 8DesafíoSigue otra llamada a una función auxiliar
¿Cuál es el orden de la salida?
def inner(): print("I") def outer(): print("O") inner() print("P") outer() print("Q")---reveal---
Las líneas son «O», «I», «P» y «Q». El cuerpo externo muestra primero su mensaje, se pausa para ejecutar
innery después se reanuda en su siguiente print. La sentencia final del nivel superior solo se ejecuta cuando terminaouter. El orden de las definiciones por sí solo no determina el orden de la salida. - 9DesafíoMueve una definición de forma segura
Un archivo define
showcon un cuerpo que llama aborder. Después definebordery termina con un bucle que llama ashow()dos veces. ¿Causará un error que la función auxiliar esté definida más abajo y cuántas veces se ejecutaráborder?---reveal---
El programa funciona: ambas definiciones se han ejecutado antes de que el bucle llame a
show. Cada llamada entra enshowdesde la primera línea de su cuerpo y llega a una llamada aborder, así que la función auxiliar se ejecuta dos veces. Mover el bucle por encima de la definición de la función auxiliar haría que su nombre no estuviera disponible cuando se necesitara por primera vez. - 10RepasoLee desde la primera sentencia activa
Al seguir la ejecución de un programa con funciones:
- Revisa la cabecera y la sangría para localizar cada cuerpo.
- Empieza por las sentencias del nivel superior y entra en un cuerpo solo mediante una llamada.
- Marca la siguiente sentencia del código que realiza la llamada antes de seguir una función auxiliar.
- Registra la salida cuando se ejecute su print.
Si una llamada falla, lee el error final de la traza y después revisa la línea del cuerpo que falla y el código que la llamó. La ruta de llamadas suele ser la clave para comprender el error.
2Ocupa las posiciones de los parámetros
13 pasos
Guarda esta unidad para seguir cada Lección Interactiva paso a paso.
- 1IntroducciónReutiliza una tarea con valores distintos
- 2EjemploAsocia la primera y la segunda entrada
- 3ExplicaciónEvalúa los argumentos antes del cuerpo
- 4DesafíoComprueba el número de argumentos
- 5ExplicaciónUsa nombres para mostrar qué representa cada valor
- 6DesafíoCorrige una posición ocupada dos veces
- 7ConsejoInterpreta las opciones por palabra clave de las funciones incorporadas
- 8EjemploHaz opcional la elección habitual
- 9DesafíoSalta una opción por su nombre
- 10Idea claveUn valor predeterminado recuerda el momento de su creación
- 11EjemploDescubre por qué una lista predeterminada conserva elementos
- 12DesafíoCombina valores predeterminados con entradas por nombre
- 13RepasoCompara la cabecera con la llamada
3Sigue los valores de vuelta al código que realiza la llamada
14 pasos
Guarda esta unidad para seguir cada Lección Interactiva paso a paso.
- 1IntroducciónObserva qué recibe el código que realiza la llamada
- 2EjemploSustituye la llamada por su resultado
- 3ExplicaciónDistingue la pantalla del resultado
- 4DesafíoEncuentra el valor usado en la suma
- 5ConsejoComprueba dónde se ejecuta la llamada
- 6EjemploDetente en la primera calificación que corresponda
- 7DesafíoCubre la entrada que queda entre las ramas
- 8Idea claveDeja que una comparación responda a la pregunta
- 9EjemploDevuelve un divisor encontrado
- 10DesafíoCorrige un resultado positivo prematuro
- 11EjemploDesempaqueta un resultado agrupado
- 12EjemploPasa un resultado interno hacia fuera
- 13DesafíoCombina una ruta anticipada y un resultado
- 14RepasoSigue conjuntamente las rutas y los valores devueltos
4Sigue los nombres y los objetos compartidos
11 pasos
Guarda esta unidad para seguir cada Lección Interactiva paso a paso.
- 1IntroducciónPregúntate a dónde pertenece el nombre
- 2EjemploDa a cada llamada su propio contador
- 3ExplicaciónDistingue los nombres que se ocultan
- 4DesafíoHaz explícita la actualización en el código que realiza la llamada
- 5EjemploSigue una lista compartida a través de un parámetro
- 6EjemploLee una variable global sin una declaración
- 7Idea claveLa asignación determina de antemano el ámbito local
- 8DesafíoElige el ámbito de una actualización
- 9ConexiónPasa el valor cambiante a través de la llamada
- 10DesafíoDistingue la mutación de la reasignación
- 11RepasoIdentifica la operación antes de predecir su efecto
5Diseña y comprueba un informe de puntuaciones
12 pasos
Guarda esta unidad para seguir cada Lección Interactiva paso a paso.
- 1IntroducciónConstruye un programa a partir de tareas claras
- 2EjemploColoca la descripción donde la ayuda pueda encontrarla
- 3ExplicaciónAñade detalles que afecten a una llamada
- 4DesafíoEncuentra la documentación que falta
- 5ExplicaciónElige una tarea para cada función auxiliar
- 6EjemploConecta las funciones auxiliares en main
- 7DesafíoSepara el cálculo de la salida en pantalla
- 8ConsejoMantén un programa que funcione mientras lo construyes
- 9EjemploComprueba un límite que pueda revelar un error
- 10DesafíoLocaliza dónde entra un tipo incorrecto
- 11DesafíoMantén la documentación y la comprobación de acuerdo
- 12RepasoUsa la interfaz para orientar las comprobaciones
Ejercicios de Funciones en Python
Set 1: Interpreta llamadas y sigue sus resultados10 Preguntas de Práctica
Pregunta 1 de 10
¿Qué salida produce este programa?
def announce():
print("Open")
print("Ready")
Mostrar respuestaOcultar respuesta
announce crea la función, pero nunca entra en su cuerpo, así que «Open» no aparece. La función incorporada print sí se ejecuta aunque nunca se llame a la función recién definida.Pregunta 2 de 10
¿Cuál es el orden de la salida?
def mark():
print("M")
def stage():
print("S")
mark()
print("T")
print("R")
stage()
Mostrar respuestaOcultar respuesta
stage muestra «S» y llama a mark, que muestra «M». Cuando termina esa llamada interna, stage se reanuda y muestra «T». Mover «M» al final pasa por alto que el código que realiza la llamada espera a su función auxiliar antes de continuar.Pregunta 3 de 10
¿Qué muestra esta llamada?
def describe_trip(origin, destination):
print(origin, "to", destination)
describe_trip("Mesa", "Salem")
Mostrar respuestaOcultar respuesta
origin y el segundo ocupa destination, así que el cuerpo muestra «Mesa to Salem». Invertir los nombres exigiría invertir los argumentos o las funciones de los parámetros en el cuerpo. Python asocia posiciones sin interpretar qué significan los nombres de las ciudades.Pregunta 4 de 10
¿Cómo puedes llamar a esta función usando «Inez» para la persona y «West» para la habitación?
def show_booking(person, room):
print(person, room)
Mostrar respuestaOcultar respuesta
room y person ocupa ambos parámetros correctamente incluso en orden inverso. Proporcionar un valor posicional después de person="Inez" es un error de sintaxis, así que los valores deseados por sí solos no hacen válida esa llamada. Las palabras clave también deben usar los nombres exactos de la cabecera y no ocupar un parámetro dos veces.Pregunta 5 de 10
¿Qué se muestra?
def label(text, copies=2):
print(text * copies)
label("Go")
Mostrar respuestaOcultar respuesta
text y omite copies, así que copies toma su valor predeterminado de 2. Multiplicar «Go» por 2 repite el texto como «GoGo» sin insertar un espacio. Mostrar solo «Go» ignoraría el valor predeterminado usado por esta llamada.Pregunta 6 de 10
¿Qué muestra la última línea?
def triple(value):
print(value * 3)
answer = triple(4)
print(answer)
Mostrar respuestaOcultar respuesta
None. La asignación guarda ese valor devuelto en answer, así que la última línea muestra «None». El 12 mostrado es un efecto del print interno y no se convierte automáticamente en el valor de retorno de la función auxiliar.Pregunta 7 de 10
¿Qué devuelve esta función para first_factor(25)?
def first_factor(n):
for candidate in range(2, n):
if n % candidate == 0:
return candidate
return n
Mostrar respuestaOcultar respuesta
return n en esa primera iteración del bucle y devuelve 25. La función nunca comprueba el candidato 5. Un return después de todo el bucle permitiría continuar la búsqueda, pero aquí la sangría coloca esa alternativa dentro del bucle.Pregunta 8 de 10
¿Cuáles son las dos líneas de salida?
level = 7
def show_level():
level = 3
print(level)
show_level()
print(level)
Mostrar respuestaOcultar respuesta
show_level crea un level local, así que la función auxiliar muestra «3». Deja el valor global en 7, que muestra el print final. Esperar dos 3 trata una asignación local como si reasignara la variable global con el mismo nombre.Pregunta 9 de 10
¿Qué función cumple la primera cadena en esta función?
def square(n):
"""Return the square of n."""
return n * n
Mostrar respuestaOcultar respuesta
square.__doc__. Llamar a square sigue devolviendo la expresión numérica n * n. Una cadena de documentación describe la función; no es una salida automática ni su sentencia return.Pregunta 10 de 10
Mostrar respuestaOcultar respuesta
None al código que la llama. Mantener la entrada y la salida en pantalla en el código que realiza la llamada facilita reutilizar y comprobar el cálculo.Set 2: Sigue las entradas, el ámbito y los resultados que faltan10 Preguntas de Práctica
Guarda esta unidad para ver todas las respuestas y practicar cada set.
Pregunta 1 de 10
¿Cómo debe completarse el cuerpo de esta función sin terminar para que el archivo sea válido, pero la función aún no haga nada?
def print_ticket():
# Work to be added later
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 2 de 10
¿Qué muestra este programa?
def show_scaled(value, factor):
print(value * factor)
entry = "6"
show_scaled(entry, 3)
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 3 de 10
¿Qué valor se devuelve?
step = 4
def advance(position, amount=step):
return position + amount
step = 9
result = advance(10)
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 4 de 10
¿Qué único cambio hace que result contenga 16 sin mostrarlo dentro de la función auxiliar?
def square(n):
print(n * n)
result = square(4)
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 5 de 10
¿Qué se muestra?
def pack(total, size):
return total // size, total % size
def double(n):
return n * 2
boxes, spare = pack(29, 6)
print(double(boxes) + spare)
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 6 de 10
¿Qué se muestra después de ambas llamadas?
def add_guest(guests):
guests.append("Sol")
def replace_guests(guests):
guests = ["Tao"]
party = ["Ren"]
add_guest(party)
replace_guests(party)
print(party)
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 7 de 10
¿Qué ocurre cuando se llama a inspect()?
count = 11
def inspect():
print(count)
count = 2
inspect()
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 8 de 10
¿Qué contiene show.__doc__?
def show():
value = 2
"""Display the current value."""
print(value)
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 9 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 10 de 10
> 50?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Set 3: Diagnostica llamadas y corrige el comportamiento del programa10 Preguntas de Práctica
Guarda esta unidad para ver todas las respuestas y practicar cada set.
Pregunta 1 de 10
¿Por qué funciona este programa aunque tick esté definida debajo de report?
def report():
tick()
def tick():
print("Done")
report()
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 2 de 10
¿Qué valor de argumento llega a width?
def show_width(width):
print(width)
base = 8
show_width(base + 3)
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 3 de 10
¿Por qué falla esta llamada?
def mark_pages(first, last):
print(first, last)
mark_pages(4, first=9)
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 4 de 10
¿Cuáles son las dos listas mostradas?
def collect(value, bucket=[]):
bucket.append(value)
return bucket
print(collect("red"))
print(collect("blue", []))
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 5 de 10
¿Cuál es la salida completa?
def shift(n):
return n + 2
print("shifted")
shift(5)
print("done")
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 6 de 10
Una función debe devolver True exactamente cuando un entero sea primo. ¿Por qué este cuerpo acepta erróneamente 35?
def is_prime(n):
if n < 2:
return False
for d in range(2, n):
if n % d == 0:
return False
else:
return True
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 7 de 10
¿Qué se muestra?
total = 2
def add(amount):
global total
total = total + amount
return total
first = add(4)
second = add(first)
print(total, second)
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 8 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 9 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 10 de 10
if score >= 60: después de que el código que la llama pase input("Score: "). ¿Qué corrección resuelve el tipo de entrada?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Set 4: Combina las reglas de las funciones en situaciones nuevas10 Preguntas de Práctica
Guarda esta unidad para ver todas las respuestas y practicar cada set.
Pregunta 1 de 10
¿Qué muestra la última línea?
def change(values):
values.append("B")
values = ["C"]
values.append("D")
return values
original = ["A"]
result = change(original)
print(original, result)
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 2 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 3 de 10
¿Qué se muestra?
def outer():
inner()
print("Y")
outer()
def inner():
print("X")
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 4 de 10
¿Cuál es la salida completa, incluidos los saltos de línea?
print("N", "S", sep="/", end="|")
print("E", "W", sep="-")
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 5 de 10
Una llamada nueva que omita items debe empezar con una lista nueva, pero una lista proporcionada debe ampliarse sobre el objeto original. ¿Qué cuerpo de sustitución es correcto?
def add_code(code, items=None):
# replacement body
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 6 de 10
¿Qué cambio permite que esta función devuelva el primer candidato que cumpla la condición, o None solo después de que fallen todos los candidatos?
def find_divisor(n):
for d in range(3, n):
if n % d == 0:
return d
else:
return None
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 7 de 10
¿Cómo puede el código que realiza la llamada actualizar stock explícitamente sin que la función auxiliar modifique una variable global?
stock = 18
def remove(stock, amount):
return stock - amount
# caller statement
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 8 de 10
pass. El código que la llama suma su resultado a 7 y obtiene TypeError. ¿Qué debe implementarse a continuación?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 9 de 10
¿Qué se muestra?
def add_fee(amount):
return amount + 3
def twice(amount):
return amount * 2
print(twice(add_fee(5)))
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 10 de 10
¿Qué se muestra?
rate = 2
def scale(value, factor=rate):
return value * factor
def reset():
global rate
rate = 5
reset()
print(scale(3), scale(3, rate))
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
¿Te atascas con una pregunta tuya? Ayuda con Tareas
Términos Clave
A
Abstracción procedimental
letter_grade(avg) sin seguir cada comparación de umbrales del cuerpo.Argumento
area(side + 1, 2), Python calcula el primer argumento antes de iniciar el cuerpo de la función de área.Argumento por palabra clave
describe_pet(name="Milo", animal="cat") ocupa los parámetros en un orden fácil de leer.Argumento posicional
describe_pet(animal, name), describe_pet("cat", "Milo") coloca «cat» en animal.Á
Ámbito
make_greeting() no está disponible para un print del nivel superior después de la llamada.C
Cabecera
def, el nombre de la función, los paréntesis de los parámetros y dos puntos.def print_line(length):, la cabecera da nombre a la tarea y a su entrada antes de que empiece el cuerpo.Cadena de documentación
Cadena de documentación de una línea
Cadena de documentación de varias líneas
tip_rate=0.2 es una fracción de la cuenta y no 20.Código que realiza la llamada
banner() llama a line(), el cuerpo de banner es el código que realiza la llamada a la función que dibuja la línea.Constante
TAX_RATE = 0.25 para calcular un impuesto sin declarar global ese nombre.Cuerpo de la función
print con sangría debajo de def greet(): pertenecen al cuerpo de la función.D
Definición de función
def con una cabecera y un cuerpo con sangría que crea una función con un nombre.greet en def greet(): y espera a una llamada antes de ejecutar su cuerpo.Desarrollo incremental
Descomposición
Desempaquetado
share(17, 5) devuelve 17 // 5, 17 % 5, la asignación each, left = share(17, 5) coloca 3 en each y 2 en left.E
end
end de print controla el texto que se añade después de los valores mostrados y usa un salto de línea de forma predeterminada.end="..." permite que el siguiente print continúe después de los puntos en lugar de empezar una línea nueva.Esbozo de función
pass crean un esbozo válido, aunque sus llamadas siguen devolviendo None hasta que se implemente.Estado oculto
F
Flujo de ejecución
banner(), terminar sus llamadas a funciones auxiliares y después mostrar «End».Función
print_receipt() cada vez que necesite mostrar otro recibo.Función booleana
True o False, a menudo directamente a partir de una comparación.return n % 2 == 0 permite usar is_even(n) directamente como condición de un if.Función con valor de retorno útil
Función sin valor de retorno útil
None.None.H
help
help muestra información sobre una función, incluidas su firma y su cadena de documentación guardada, si la hay.help(to_fahrenheit) para consultar el conversor sin proporcionarle primero una temperatura.I
Interfaz
L
Llamada a función
greet() ejecuta el saludo, mientras que una línea que solo contiene greet no lo hace.Llamada anidada
print(to_fahrenheit(add(10, 15))), se ejecuta la suma antes de la conversión y después se muestra el resultado.M
main
main coordina las tareas más pequeñas de un programa y conecta las entradas, los resultados de las funciones auxiliares y la salida final en pantalla.main() ejecuta los pasos de un informe de puntuaciones después de que se hayan ejecutado todas las definiciones de las funciones auxiliares.Mutación
N
None
None es el valor especial de Python que significa «sin valor» y también sirve como señal de que se ha omitido una entrada opcional.basket=None, la función puede crear una lista nueva dentro de if basket is None:.O
Ocultación de nombres
x = 5 localmente mientras que x = 10 es global, la x de la función auxiliar produce 5 y una x global posterior sigue produciendo 10.P
Parámetro
def area(width, height): proporciona a cada llamada de área nombres locales para sus dos dimensiones.Parámetro obligatorio
def greet(name, greeting="Hello"):, omitir name causa un error por falta de un argumento.Parámetro opcional
milk="oat" mientras deja un parámetro opcional anterior de cantidad de dosis de café con su valor predeterminado.Paso combinado de argumentos posicionales y por palabra clave
describe_pet("cat", name="Milo"), la primera posición se ocupa por posición y la segunda por nombre.pass
pass es un marcador provisional que no realiza ninguna acción y permite que el cuerpo de una función prevista sea código Python válido.pass puede llamarse mientras aún se está escribiendo su comportamiento real de salida en pantalla.Pila de llamadas
Prueba de valores límite
> en lugar de >=.R
Reasignación
points = points + 10 modifica el parámetro local y deja intacta la puntuación del código que realiza la llamada.Resultado esperado
Retorno anticipado
Ruta de retorno
S
Salida de depuración
Sentencia global
global hace que un nombre dentro de una función se refiera a la vinculación del nivel del archivo en las lecturas y asignaciones posteriores.global total antes de que la función use total para actualizar un contador acumulado compartido.Sentencia return
None.return width * height permite que el código que realiza la llamada guarde un área o la use en otro cálculo.sep
sep de print controla el texto que se inserta entre los valores mostrados y usa un espacio de forma predeterminada.print("a", "b", "c", sep="-") muestra las tres letras como «a-b-c».T
Traza de la excepción
Tupla
return total // people, total % people agrupa una parte del reparto y un resto.TypeError
TypeError informa de una operación inadecuada sobre un valor o de una llamada con una combinación de argumentos no válida.TypeError por la entrada que falta.U
UnboundLocalError
UnboundLocalError se produce cuando una función intenta leer un nombre local antes de que ese nombre tenga un valor.count hace que un print(count) anterior también sea local, aunque exista una variable global.V
Valor de retorno
area = rectangle_area(4, 2.5), area contiene el resultado devuelto 10,0 para usarlo más adelante.Valor predeterminado
def greet(name, greeting="Hello"):, una llamada puede omitir el saludo y seguir proporcionando el nombre.Valor predeterminado mutable
Variable global
x = 10 del nivel superior sigue valiendo 10 cuando una función auxiliar asigna su propia variable local independiente x = 5.Variable local
count = 0, así que dos llamadas pueden mostrar el valor 1 de forma independiente.Sobre esta unidad
Crea tus propios Materiales de Estudio
Convierte tus notas, diapositivas y documentos en Guías de Estudio, Preguntas de Práctica, Flashcards y 6 herramientas más.