Recursos libres para aprender a programar en español
Basado en https://github.com/mumukiproject/mumuki-guia-python3-variables-y-procedimientos-2021
Cuando programamos, ¿siempre vamos a querer retornar algo? ¿Habrá alguna especie de función que no retorne? Y si no retorna, ¿es una función? 🤔
En esta lección vamos a conocer a las variables y los procedimientos, dos herramientas que nos van a pemitir solucionar nuevos tipos problemas y hacer programas más complejos. 🕶️
En programación buscamos resolver nuestros problemas usando… programas 😜. Y entre los problemas que casi nadie quiere resolver están los matemáticos. Sobre todo aquellos en los que aparecen números, como pi, con infinitos decimales imposibles de recordar. 🤕
Considerando al número pi igual a
3.14159265358979
(no es infinito pero lo suficientemente preciso para nuestros cáculos), definí las funcionesperimetro_circulo
yarea_circulo
que reciben el radio de un círculo y nos devuelven su perímetro y su área.
El perímetro se calcula como dos veces pi por el radio de un círculo. El área, en cambio, es el resultado de hacer pi por radio por radio.
Probá las siguientes consultas y verificá que devuelvan lo mismo:
>>> perimetro_circulo(1)
6.28318530717958
>>> perimetro_circulo(2)
12.56637061435916
>>> perimetro_circulo(0)
0
>>> area_circulo(1)
3.14159265358979
>>> area_circulo(2)
12.56637061435916
>>> area_circulo(0)
0
Excelente, la precisión de nuestros cálculos es innegable 🧐, pero tuvimos que escribir un número larguísimo. Pensemos que pi aparece en un montón de fórmulas matemáticas. ¿Es necesario escribir este número cada vez?¿No podemos hacer algo más cómodo? 🤔
Por suerte existe una herramienta que va a simplificar nuestra tarea de ahora en adelante: las variables. 😁
Las variables nos permiten nombrar y reutilizar valores. Similar a cómo las funciones nos permiten dar nombres y reutilizar soluciones a problemas más pequeños. Por ejemplo, si hacemos…
primer_mes = "enero"
…estamos asignándole el valor "enero"
a la variable primer_mes
. En criollo, estamos dándole ese valor a la variable. 😌
Cambiá los lugares donde aparece
3.14159265358979
por la variablepi
en las funciones que tenemos definidas.
Probá las siguientes consultas y verificá que devuelvan lo mismo:
>>> perimetro_circulo(1)
6.28318530717958
>>> perimetro_circulo(2)
12.56637061435916
>>> perimetro_circulo(0)
0
>>> area_circulo(1)
3.14159265358979
>>> area_circulo(2)
12.56637061435916
>>> area_circulo(0)
0
¡Excelente! Gracias a la variable pi
no tuvimos que escribir el número cada vez que teníamos que usarlo y ¡nuestro programa quedó mucho más entendible! 🙌
Ya que vas entendiendo cómo se asignan las variables, te traemos algo para pensar: ¿qué pasa si intento usar una variable a la que nunca le asigné un valor? 😱
¡Averigüémoslo! Tenemos esta función definida:
def suma_sin_sentido(): return numero + 8
Invocala en la consola y fijate qué sucede.
Probá las siguientes consultas y verificá que devuelvan lo mismo:
def suma_sin_sentido():
return numero + 8
Entonces, ¿es necesario darle valor a nuestras variables antes de usarlas? 🤔
Para evitar errores ❌ , antes de utilizar una variable tenemos que darle un valor inicial, es decir, inicializarla.
Definí una función
ascensor_sobrecargado
, que toma una cantidad de personas y dice si entre todas superan la carga máxima:>>> ascensor_sobrecargado(1) False >>> ascensor_sobrecargado(100) True
Ah, y ¿cuál es el peso promedio de una persona? ¿Y la carga máxima? Para eso utilizaremos dos variables:
peso_promedio_persona_en_kilogramos
, la cual ya está incializada,carga_maxima_en_kilogramos
que vas a tener que inicializar en300
Probá las siguientes consultas y verificá que devuelvan lo mismo:
>>> peso_promedio_persona_en_kilogramos = 70
>>> ascensor_sobrecargado(4)
False
>>> peso_promedio_persona_en_kilogramos = 80
>>> ascensor_sobrecargado(4)
True
>>> peso_promedio_persona_en_kilogramos = 80
>>> ascensor_sobrecargado(2)
False
>>> peso_promedio_persona_en_kilogramos = 80
>>> ascensor_sobrecargado(5)
True
¡Excelente! 👏
Con lo que venimos haciendo cualquier función puede utilizar a las variables, pero ¿qué pasa si no queremos que eso pase? 🤔
Hay veces que no queremos, o simplemente no tiene sentido, que nuestras variables sean accedidas por todas las funciones. Por suerte, podemos inicializar variables tanto directamente en el programa, como dentro de un def
:
def el_mas_largo_sin_espacios(un_string, otro_string):
un_string_sin_espacios = str.strip(un_string)
otro_string_sin_espacios = str.strip(otro_string)
if(len(un_string_sin_espacios) > len(otro_string_sin_espacios)):
return un_string_sin_espacios
else:
return otro_string_sin_espacios
Las variables inicializadas dentro de un def
, conocidas como variables locales, no presentan mayor misterio. Sin embargo, hay que tener un particular cuidado ⚠️ ya que sólo se pueden utilizar dentro del def
en cuestión. Si quiero referenciarla desde un programa…
pregunta = "¿" + un_string_sin_espacios + "?"
…¡boom! ¡se romperá! 💥
Sin embargo, las variables inicializadas directamente en el programa, conocidas como variables globales, pueden ser leídas desde cualquier def
. Por ejemplo:
peso_maximo_del_equipaje_en_gramos = 5000
def puede_llevar(peso_equipaje):
return peso_equipaje <= peso_maximo_del_equipaje_en_gramos
Como te habrás dado cuenta, nunca nos olvidamos de saludar ¡y ahora no es la excepción!
Modificá la función
saludar_a
para evitar la repetición de lógica. Para eso utilizá una variable localfinal_de_saludo
.
Probá las siguientes consultas y verificá que devuelvan lo mismo:
>>> saludar_a("Gus", 11)
"¡Buenos días Gus!"
>>> saludar_a("May", 12)
"¡Buenas tardes May!"
>>> saludar_a("Lu", 18)
"¡Buenas tardes Lu!"
>>> saludar_a("Guille", 19)
"¡Buenas noches Guille!"
>>> saludar_a("Jor", 20)
"¡Buenas noches Jor!"
¡Excelente! 🙌
Para resumir lo visto:
Si bien ahora conocemos los dos tipos de variables no abusemos de su uso. Recordemos que las variables nos sirven para utilizar un mismo valor en más de un lugar y evitar la repetición de lógica.
Todo muy lindo hasta acá, pero ¿por qué se llaman variables si no varian? 🤨
Bueno, es que en realidad sí pueden variar 🕶️ . Veamos un ejemplo:
# inicializamos la variable para que valga 0...
dias_sin_accidentes_con_velocirraptores = 0
# ...y más adelante, la actualizamos
dias_sin_accidentes_con_velocirraptores = dias_sin_accidentes_con_velocirraptores + 1
# ¡ahora vale 1!
dias_sin_accidentes_con_velocirraptores
Sin embargo, hay que tener un cuidado particular si trabajamos con variables globales: si queremos modificarlas dentro de una función, deberemos anteponer global
a su nombre:
# inicializamos la variable al inicio de nuestro programa
dias_sin_accidentes_con_velocirraptores = 0
def pasar_un_dia_normal():
# indicamos a Python que vamos a realizar modificaciones sobre la variable global
global dias_sin_accidentes_con_velocirraptores
# acá adentro la actualizamos
dias_sin_accidentes_con_velocirraptores = dias_sin_accidentes_con_velocirraptores + 1
Probá en la consola, en orden, lo siguiente:
dias_sin_accidentes_con_velocirraptores
pasar_un_dia_normal()
pasar_un_dia_normal()
pasar_un_dia_normal()
dias_sin_accidentes_con_velocirraptores
Podés usar las flechas de tu teclado para navegar entre comandos ejecutados previamente. 🔼 🔽
Probá las siguientes consultas y verificá que devuelvan lo mismo:
dias_sin_accidentes_con_velocirraptores = 0
def pasar_un_dia_normal():
global dias_sin_accidentes_con_velocirraptores
dias_sin_accidentes_con_velocirraptores = dias_sin_accidentes_con_velocirraptores + 1
¡Varió! O mutó como solemos decir. Pero tené en cuenta que poder hacerlo, no significa querer hacerlo. No siempre vamos a querer modificar el valor de nuestras variables. 😌
Si te preguntas por qué es necesario anteponer global
, tené en cuenta que las variables globales pueden ser accedidas por cualquier función. Es la manera que tenemos de asegurar que sabemos eso y que aún así queremos modificar nuestra variable. 😌
¿Notaste algo distinto en la “función” del ejercicio anterior 🔍? Veámosla nuevamente:
def pasar_un_dia_normal():
global dias_sin_accidentes_con_velocirraptores
dias_sin_accidentes_con_velocirraptores = dias_sin_accidentes_con_velocirraptores + 1
¡No tiene return
! Pero, ¿las funciones no tienen todas un return
? 🧐
Correcto, es que en realidad pasar_un_dia_normal()
no es una función, ¡es un procedimiento! 😮 Si bien tanto funciones como procedimientos se definen de la misma manera y ambos nos ayudan a simplificar nuestras tareas, tienen algunas diferencias:
Ahora que sabes la diferencia, definí un procedimiento
aumentar_fortuna
que duplique el valor de la variable globalpesos_en_mi_billetera
. No inicialices la variable, porque ya lo hicimos por vos (con una cantidad secreta de dinero 😉).
Probá las siguientes consultas y verificá que devuelvan lo mismo:
>>> pesos_en_mi_billetera = 0
>>> pesos_en_mi_billetera = 100
>>> aumentar_fortuna()
>>> pesos_en_mi_billetera
200
>>> pesos_en_mi_billetera = 30
>>> aumentar_fortuna()
>>> aumentar_fortuna()
>>> aumentar_fortuna()
>>> pesos_en_mi_billetera
240
Actualizaciones como duplicar, triplicar, incrementar en uno o en una cierta cantidad son tan comunes que Python presenta algunos atajos:
x += y # equivalente a x = x + y
x *= y # equivalente a x = x * y
x -= y # equivalente a x = x - y
¡Usalos cuando quieras! 😉
Ahora que conocimos a los procedimientos podemos modelar casos de alternancia utilizando not
. Por ejemplo, prender y apagar una luz 💡:
luz_prendida = False
def apretar_interruptor():
global luz_prendida
luz_prendida = not luz_prendida
¡Ahora te toca a vos!
Definí el procedimiento
usar_cierre
para que podamos abrir y cerrar nuestra mochila. 🎒
Probá las siguientes consultas y verificá que devuelvan lo mismo:
>>> usar_cierre()
>>> mochila_abierta
False
>>> mochila_abierta = False
>>> usar_cierre()
>>> mochila_abierta
True
>>> usar_cierre()
>>> usar_cierre()
>>> mochila_abierta
True
Con todo lo que aprendimos hasta acá estaría bueno cortar para tomar unos mates, ¿no? 🧉 Mejor aún, ¡programemos los mates! 😓
Sabiendo que al cebar un mate la cantidad de agua del termo disminuye…
…inicializá la variable global
agua_del_termo
(que representa los mililitros que tiene el termo) con 1000. También definí el procedimientocebar_mate
que disminuye 30 mililitros del agua en el termo.
Probá las siguientes consultas y verificá que devuelvan lo mismo:
>>> agua_del_termo = 1000
>>> cebar_mate()
>>> agua_del_termo
970
>>> agua_del_termo = 1000
>>> cebar_mate()
>>> cebar_mate()
>>> cebar_mate()
>>> agua_del_termo
910
Sin importar cuan bueno sea el termo, algunas veces el agua simplemente se enfría. 😖
Definí los procedimientos:
vaciar_termo
que saca todo elagua_del_termo
, es decir, deja en 0 la variable;llenar_termo
que vuelve a poner nuestra variable en 1000.
Probá las siguientes consultas y verificá que devuelvan lo mismo:
global agua_del_termo
agua_del_termo = 1000
vaciar_termo()
self.assertEqual(agua_del_termo, 0)
global agua_del_termo
agua_del_termo = 80
llenar_termo()
self.assertEqual(agua_del_termo, 1000)
A veces no hace falta llenar tooooodo el termo, con un poco de agua quizás alcanza. 💧
Definí el procedimiento
cargar_termo
que espere una cantidad de agua como argumento y aumente elagua_del_termo
en esa cantidad.
Probá las siguientes consultas y verificá que devuelvan lo mismo:
>>> agua_del_termo = 600
>>> cargar_termo(200)
>>> agua_del_termo
800
>>> agua_del_termo = 200
>>> cargar_termo(500)
>>> agua_del_termo
700
Todo bien con el termo, pero ¿dónde está el mate? 🧉
Ya hicimos toda la lógica relacionada con el agua del termo, pero del mate ni noticias. 😒
Vamos a modificar un poco el programa que teníamos:
- Inicializá la variable
agua_del_mate
en 0.- Modificá el procedimiento
cebar_mate
para que, además de lo que hacía, aumente en 30 mililitros elagua_del_mate
.- Definí el procedimiento
tomar_mate
que deja en 0 el agua del mate.
Probá las siguientes consultas y verificá que devuelvan lo mismo:
>>> agua_del_termo = 1000
>>> cebar_mate()
>>> agua_del_termo
970
>>> agua_del_termo = 1000
>>> cebar_mate()
>>> cebar_mate()
>>> cebar_mate()
>>> agua_del_termo
910
>>> agua_del_mate = 0
>>> cebar_mate()
>>> agua_del_mate
30
>>> agua_del_mate = 20
>>> tomar_mate()
>>> agua_del_mate
0
Bueno, ya es bastante mate, ¿no? 👀
Recordemos que la educación está ante todo. 😌
Es conocimiento popular que cuando no queremos más mate solo basta con decir Gracias. ☺️
Para modelar esta lógica vamos a definir el procedimiento pasar
que no va a hacer nada. Sin embargo, no va a ser un procedimiento vacío sino que va a estar definido de la siguiente manera:
def pasar():
pass
Probalo en la consola haciendo lo siguiente en orden:
agua_del_mate
agua_del_termo
cebar_mate()
agua_del_mate
pasar()
agua_del_mate
agua_del_termo
Probá las siguientes consultas y verificá que devuelvan lo mismo:
agua_del_mate = 0
agua_del_termo = 1000
def cebar_mate():
global agua_del_mate
global agua_del_termo
agua_del_termo -= 30
agua_del_mate += 30
def tomar_mate():
global agua_del_mate
agua_del_mate = 0
def pasar():
pass
Te preguntarás por qué no dejamos vacío el procedimiento y ya, ¿no?
Es que en Python no podemos definir un procedimiento vacío…
def pasar():
…tampoco con solo un comentario…
def pasar():
# Paso
…dado que los comentarios son ignorados. Sin embargo, pass
es tenido en cuenta ya que es la representación en código de “no hacer nada”. 🤯
Mirá el siguiente programa con atención 👀 :
volumen = 40
def subir_volumen(decibeles):
global volumen
volumen += decibeles
def bajar_volumen(decibeles):
global volumen
volumen -= decibeles
def es_volumen_saludable():
return volumen <= 75
Marcá las afirmaciones correctas:
volumen
es una variable localvolumen
es una variable globalsubir_volumen
es una funciónsubir_volumen
es un procedimientobajar_volumen
es una funciónbajar_volumen
es un procedimientoes_volumen_saludable
es una funciónes_volumen_saludable
es un procedimientosubir_volumen
retorna un númeroes_volumen_saludable
retorna un númeroes_volumen_saludable
retorna un booleano¡Perfecto! 👌
A lo largo de esta lección hiciste muchas cosas nuevas:
¡Veamos que depara la siguiente lección! 👀