<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 22/10
Entrada y salida de datos
Funciones (parámetros por default, nombrados), módulos (distintas formas de importarlos)
CLASE DE LABORATORIO 
Vencimiento TP1
Enunciado del TP 2
Funciones
Una de las premisas de Python era que "La legibilidad cuenta", y el uso de funciones ayudan mucho en que un código sea legible. <br>
En Python no existen los procedimientos
Step1:  Aunque en ningún momento indicamos que lo que tiene que sumar son números, por lo que también puede sumar strings
Step3:  Además, a esta función le podría agregar comentarios (docstrings) para que al hacer help de la función se entienda qué es lo que hace
Step5:  El resultado de la función no es necesario que lo guarde en una variable, tranquilamente la puedo invocar y perder ese valor.
Step6:  ¿Y qué sucede si no pongo el return en una función?
Step7:  ¿Y si le asigno el resultado de este procedimiento a una variable?
Step8:  Por lo que no existen los procedimientos, los "procedimientos" en realidad son funciones que devuelven None.
Y una prueba más de esto es el resultado de llamar a la función type y pasarle como parámetro la función sumar y el "procedimiento" imprimir
Step9:  Ahora, si la función es un tipo de dato, significa que se lo puedo asignar a una variable...
Step10:  ¿Y qué pasa si ahora llamo a mi_suma con los parámetros 1 y 2 como hice antes con sumar?
Step11:  Lista de parámetros
¿Qué pasa cuando no sabemos cuántos parámetros nos pueden pasar, pero si sabemos qué hacer con ellos?
Step12:  Parámetros por defecto
Algo más común que no saber la cantidad de parámetros que nos van a pasar es asumir que ciertos parámetros pueden no pasarlos y para ellos asumiremos un valor por defecto. <br>
Por ejemplo
Step13:  Para esta función nos pueden pasar 2, 3, 4 o 5 parámetros. Si nos pasan los 5 parámetros, se imprimirán los valores que nos pasen
Step14:  Ahora, si nos pasan 4 parámetros, el intérprete asumirá que el faltante es param5, por lo que dicho parámetro tomará el valor False. Y lo mismo pasa con el resto de los parámetros.
Step15:  ¿Y si le pasamos un sólo parámetro?.
Step16:  ¿Y qué pasa si quiero pasarle los parámetros 1, 2 y el 5?. <br>
No es problema, para eso tenemos que usar parámetros nombrados
Step17:  Lo mismo pasa si lo que quiero cambiar es el cuatro parámetro
Step18:  Hasta se pueden nombrar todos los parámetros
Step19:  Si bien puede parecer innecesario el uso de parámetros nombrados, en algunas oportunidades se suele usar para agregar claridad y legibilidad al código, y en otros para pasarle un diccionario
Step20:  Uso de módulos externos
Así como en Pascal usando la cláusula Uses podíamos usar código que no pertenecía al archivo que estábamos codificando, en Python podemos hacer lo mismo usando la cláusula import y poniendo a continuación el nombre del módulo. <br>
Por ejemplo, si queremos importar el módulo datetime para trabajar con fechas y horas, tendríamos que hacer
Step21:  Pero a diferencia de Pascal y C, acá podemos elegir importar una función o algo en particular de ese módulo, en lugar de traerlo todo. Para eso tendríamos que poner en primer lugar la cláusula from, luego el nombre del módulo y a continuación la cláusula import todo lo que queremos importar separada por comas. <br>
Por ejemplo, del módulo datetime podríamos traer los submódulos date y time. Después, para usarlos simplemente lo hacemos llamando lo que importamos sin el nombre del módulo. <br>
<ASSISTANT_TASK:>
Python Code:
def sumar(x, y):  # Defino la función sumar
    return x + y
x = 4
z = 5
print sumar(x, z)  # Invoco a la función sumar con los parámetros x y z
print sumar(1, 2)  # Invoco a la función sumar con los parámetros 1 y 2
Explanation: 22/10
Entrada y salida de datos
Funciones (parámetros por default, nombrados), módulos (distintas formas de importarlos)
CLASE DE LABORATORIO 
Vencimiento TP1
Enunciado del TP 2
Funciones
Una de las premisas de Python era que "La legibilidad cuenta", y el uso de funciones ayudan mucho en que un código sea legible. <br>
En Python no existen los procedimientos: son todas funciones. Incluso, aunque nosotros no devolvamos ningún valor, Python lo hará por nosotros, retornando None. <br>
La forma de devolver valores es, al igual que en C, usando la palabra reservada return y el valor a retornar. Y de igual forma, una vez que se ejecuta esa sentencia, no se ejecuta ninguna sentencia más de esa función; sin importar si está dentro de un ciclo o todavía no hayamos hecho nada. <br>
La definición de una función comienza usando la palabra reservada def, y continúa dejando un espacio, poniendo el nombre de la función, los parámetros entre paréntesis(los paréntesis son obligatorios por más que no se pasen parámetros) y un dos puntos para terminar la línea. En las líneas que le siguen va el código de la función, que, al igual que para las estructuras de control, la forma en que se indica el bloque de código que se tiene que ejecutar es haciendo uso de la indentación.<br>
El nombre de la función tiene que cumplir las mismas reglas para las variables, puede empezar con cualquier letra y el _ y después le puede seguir cualquier carácter alfanumérico más el _. <br>
Por ejemplo:
End of explanation
print sumar('hola ', 'mundo')
Explanation: Aunque en ningún momento indicamos que lo que tiene que sumar son números, por lo que también puede sumar strings:
End of explanation
def sumar(x, y):
    Suma dos elementos y retorna el resultado.
    
    return x + y
help(sumar)
Explanation: Además, a esta función le podría agregar comentarios (docstrings) para que al hacer help de la función se entienda qué es lo que hace:
End of explanation
def factorial(n):
    Calcula el factorial de un número de forma iterativa.
    
    for i in range(1,n):
        n *= i
    return n
fact_5 = factorial(5)  # calculo el factorial de 5 y lo guardo en fact_5
factorial(10)  # calculo el factorial de 10 y no lo guardo en ninguna variable
Explanation: El resultado de la función no es necesario que lo guarde en una variable, tranquilamente la puedo invocar y perder ese valor.
End of explanation
def imprimir(msg):
    print msg
    
imprimir('Hola mundo')
Explanation: ¿Y qué sucede si no pongo el return en una función?
End of explanation
resultado = imprimir('Hola mundo')
print resultado
Explanation: ¿Y si le asigno el resultado de este procedimiento a una variable?
End of explanation
print type(imprimir)
print type(sumar)
print sumar
Explanation: Por lo que no existen los procedimientos, los "procedimientos" en realidad son funciones que devuelven None.
Y una prueba más de esto es el resultado de llamar a la función type y pasarle como parámetro la función sumar y el "procedimiento" imprimir:
End of explanation
mi_suma = sumar
Explanation: Ahora, si la función es un tipo de dato, significa que se lo puedo asignar a una variable...
End of explanation
print mi_suma(1, 2)
Explanation: ¿Y qué pasa si ahora llamo a mi_suma con los parámetros 1 y 2 como hice antes con sumar?
End of explanation
def sumar(*args):
    suma = 0
    for e in args:
        suma += e
    return suma
print sumar(1, 2)
print sumar(1, 2, 3, 4, 5)
print sumar(*[1, 2, 3, 4, 5, 6])
print sumar
Explanation: Lista de parámetros
¿Qué pasa cuando no sabemos cuántos parámetros nos pueden pasar, pero si sabemos qué hacer con ellos?
End of explanation
def imprimir_parametros(param1, param2, param3=5, param4="es el cuarto parametro", param5=False):
    print param1, param2, param3, param4, param5
Explanation: Parámetros por defecto
Algo más común que no saber la cantidad de parámetros que nos van a pasar es asumir que ciertos parámetros pueden no pasarlos y para ellos asumiremos un valor por defecto. <br>
Por ejemplo:
End of explanation
imprimir_parametros(1, 2, 3, 4, 5)
Explanation: Para esta función nos pueden pasar 2, 3, 4 o 5 parámetros. Si nos pasan los 5 parámetros, se imprimirán los valores que nos pasen:
End of explanation
imprimir_parametros(1, 2, 3, 4)
imprimir_parametros(1, 2, 3)
imprimir_parametros(1, 2)
Explanation: Ahora, si nos pasan 4 parámetros, el intérprete asumirá que el faltante es param5, por lo que dicho parámetro tomará el valor False. Y lo mismo pasa con el resto de los parámetros.
End of explanation
imprimir_parametros(1)
Explanation: ¿Y si le pasamos un sólo parámetro?.
End of explanation
imprimir_parametros(1, 2, param5="Este el parametro5")
Explanation: ¿Y qué pasa si quiero pasarle los parámetros 1, 2 y el 5?. <br>
No es problema, para eso tenemos que usar parámetros nombrados:
End of explanation
imprimir_parametros(1, 2, param4=4)
Explanation: Lo mismo pasa si lo que quiero cambiar es el cuatro parámetro:
End of explanation
imprimir_parametros(param5=1, param3=2, param1=3, param2=4, param4=5)
Explanation: Hasta se pueden nombrar todos los parámetros:
End of explanation
parametros = {
    'param1': 1,
    'param2': 2,
    'param3': 3,
    'param4': 4,
    'param5': 5,
}
imprimir_parametros(**parametros)
Explanation: Si bien puede parecer innecesario el uso de parámetros nombrados, en algunas oportunidades se suele usar para agregar claridad y legibilidad al código, y en otros para pasarle un diccionario:
End of explanation
import datetime
print datetime.date.today()
Explanation: Uso de módulos externos
Así como en Pascal usando la cláusula Uses podíamos usar código que no pertenecía al archivo que estábamos codificando, en Python podemos hacer lo mismo usando la cláusula import y poniendo a continuación el nombre del módulo. <br>
Por ejemplo, si queremos importar el módulo datetime para trabajar con fechas y horas, tendríamos que hacer:
Python
import datetime
Para usarlo simplemente tenemos que poner el nombre del módulo, un punto y la función que queramos usar. <br>
En este caso, dentro del módulo datetime vamos a usar la función que se encuentra en date y se llama today().
End of explanation
from datetime import date, time
print date.today()
print time(1, 23, 32)
Explanation: Pero a diferencia de Pascal y C, acá podemos elegir importar una función o algo en particular de ese módulo, en lugar de traerlo todo. Para eso tendríamos que poner en primer lugar la cláusula from, luego el nombre del módulo y a continuación la cláusula import todo lo que queremos importar separada por comas. <br>
Por ejemplo, del módulo datetime podríamos traer los submódulos date y time. Después, para usarlos simplemente lo hacemos llamando lo que importamos sin el nombre del módulo. <br>
End of explanation
<END_TASK>