Apuntes_Python/01_curso/Modulo_1/1-3b_funciones.py

359 lines
10 KiB
Python
Raw Normal View History

2022-12-24 22:41:20 -03:00
"""
FUNCION es una secuencia de sentencias que realiza una operación.
Las mismas tienen un nombre y pueden recibir o no parámetros y
devolver o no resultados.
ej.
"""
def cero():
return 0
cero() # 0
cero() + 1 # 1
c = cero()
c # 0
def suma_uno(un_numero):
return un_numero + 1
suma_uno(3) # 4
suma_uno(cero()) #1
def suma(a, b):
resultado = a + b
return resulado
def suma(a, b):
resultado = a + b
return resulado
def maximo_2(a, b):
"Devuelve el máximo entre a y b"
maximo = a
if b > a:
maximo = b
return maximo
def maximo_3(a, b, c):
"Devuelve el máximo enter a, b, y c"
return maximo_2(a, maximo_2(b,c))
print(maximo_2(2,5)) # 5
print(maximo_3(6, 1, 5)) # 6
# MAS SOBRE FUNCIONES
def peso(masa, gravedad=9.8):
"Fórmula del peso"
return masa * gravedad
# Parametros opcionales
print("Peso en la tierra:", peso(10)) # Peso en la tierra: 98.0
print("Peso en la luna:", peso(10, 1.63)) # Peso en la luna: 16.299999999999997
# Parámetros con palabras claves (o argumentos nombrados)
print("Peso en la luna:", peso(10, gravedad=1.63)) # Peso en la luna: 16.299999999999997
print("Peso en la luna:", peso(masa=10, gravedad=1.63)) # Peso en la luna: 16.299999999999997
print("Peso en la luna:", peso(gravedad=1.63, masa=10)) # Peso en la luna: 16.299999999999997
# Los parámetros posicionales no pueden ir despues de un keyword
# print("Peso en la luna:", peso(masa=10, 1,63))
# SyntaxError: positional argument follows keyword argument
# Lista de parámetros
def suma_numeros(*args):
"Suma los números pasados por párametro"
return sum(args)
print("6 + 7 + 8 =", suma_numeros(*[6,7,8]))
# 6 + 7 + 8 = 21
print("6 + 7 + 8 =", suma_numeros(6,7,8))
# 6 + 7 + 8 = 21
# Diccionario de parámetros
def imprimir_ticket(*args, **kwargs):
"Imprime el ticket de una compra"
print("Detalle Ticket")
for item, precio in kwargs.items():
print(item, ":", precio)
# ARGUMENTOS DE FUNCIONES
"""
# FUNCIONES
- Distintas formas de pasar los argumentos
- Definir funciones anónimas o expresiones lambda
Definiedo Funciones
Función Fibonacci ( hasta limite determinado )
*def para definir la funcion
"""
>>> def fibo(n):
"""Muestra la serie Fibonacci hasta n."""
a, b = 0, 1
while a < n:
print(a, end=' ')
a, b = b, a+b
print()
fibo(2000)
# 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597
"""
* return devuelve un valor en una funcion, sin una expresion como
argumento retorna None, si se alcanza el fuba de una función,
también retorna None.
"""
f = fibo
f(1000) # 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
print(f(0)) # None
type(f) # <class 'function'>
def fibo2(n):
"""Devuelve una lista con la serie de Fobonacci hasta n."""
result = []
a, b = 0, 1
while a < n:
result.append(a)
a, b = b, a+b
return result
f100 = fibo2(100)
f100 # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
def pedir_confirmacion(prompt, reintentos=4, msj='Intenta nuevamente'):
while True:
ok = input(prompt)
if ok in ('s', 'S', 'si', 'Si', 'SI'):
return True
if ok in ('n', 'no', 'No', 'NO'):
return False
reintentos -= 1
if reintentos < 0:
raise ValueError('Respuesta de usuario invalida')
print(msj)
pedir_confirmacion('¿Quieres Salir?')
# ¿Quieres Salir?no
# False
pedir_confirmacion('¿Sobreescribir?', 2)
# ¿Sobreescribir?e
# Intenta nuevamente
# ¿Sobreescribir?3
# Intenta nuevamente
# ¿Sobreescribir?3
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
# File "<stdin>", line 10, in pedir_confirmacion
# ValueError: Respuesta de usuario invalida
# >>>
# >>>
pedir_confirmacion('Sobreescribir?', 2, 'eeey! si o no?')
# Sobreescribir?o
# eeey! si o no?
# Sobreescribir?no
# False
"""
* Los valores por omisión son evaluados en el momento de la
definición de la función, en el ámbito de la definición, entonces:
"""
i = 5
def f(arg=i):
print(arg)
i = 6
f() # 5
f(6) # 6
f() #5
""" El valor por omisión es evaluado solo una vez.
Existe una diferencia cuando el valor por omisiónes un objeto mutable
como una lista, diccionario, o instancia de la mayoría de las clases.
Por ejemplo, la siguiente funciónacumula los argumentos que se le pasan
en subsiguientes llamadas:
"""
def f(a, L=[]):
L.append(a)
return L
print(f(1)) #[1]
print(f(2)) #[1, 2]
print(f(3)) #[1, 2, 3]
"""
* Si no se quiere que el valor por omisión sea compartido entre
subsiguientes llamadas, la función se puede escribir así:
"""
>>> def f(a, L=None):
... if L is None:
... L = []
... L.append(a)
... return L
...
>>> print(f(1))
[1]
>>> print(f(2))
[2]
>>> print(f(3))
[3]
>>> print(f(1, [1,2,3]))
[1, 2, 3, 1]
>>>
"""
* Palabras clave como argumentos
Las funciones también puede ser llamadas usando argumentos de palabras clave
(o argumentos nombrados) de la formakeyword = value. Por ejemplo:
"""
def loro(tension, estado='muerto', accion='explotar', tipo='Azul Nordico'):
print("-- Este loro no va a", accion, end=' ')
print("si le aplicas", tension, "voltios.")
print("-- Gran plumaje tiene el", tipo)
print("-- Está", estado,"!")
loro(1000) # 1 argumento posicional
# -- Este loro no va a explotar si le aplicas 1000 voltios.
# -- Gran plumaje tiene el Azul Nordico
# -- Está muerto !
loro(tension=1000) # 1 argumento nombrado
# -- Este loro no va a explotar si le aplicas 1000 voltios.
# -- Gran plumaje tiene el Azul Nordico
# -- Está muerto !
loro(tension=1000000, accion='VOOOOM') # 2 argumentos nombrados
# -- Este loro no va a VOOOOM si le aplicas 1000000 voltios.
# -- Gran plumaje tiene el Azul Nordico
# -- Está muerto !
loro(accion='VOOOOM', tension=1000000) # 2 argumentos nombrados
# -- Este loro no va a VOOOOM si le aplicas 1000000 voltios.
# -- Gran plumaje tiene el Azul Nordico
# -- Está muerto !
loro('un millón', 'despojado de vida', 'saltar') # 3 args posicionales
# -- Este loro no va a saltar si le aplicas un millón voltios.
# -- Gran plumaje tiene el Azul Nordico
# -- Está despojado de vida !
loro('mil', estado='viendo crecer las flores desde abajo') # uno pos. y uno nom.
# -- Este loro no va a explotar si le aplicas mil voltios.
# -- Gran plumaje tiene el Azul Nordico
# -- Está viendo crecer las flores desde abajo !
'''Llamadas invalidas'''
loro() # falta argumento obligatorio
loro(tension=5.0, 'muerto') # argumento posicional luego de uno nombrado
loro(110, tension=220) # valor duplicado para el mismo argumento
loro(actor='Juan Garau') # nombre del argumento desconocido
"""
# Cuando un parámetro formal de la forma **nombre está presente al final,
recibe un diccionario (ver Tipos integrados) conteniendo todos los argumentos
nombrados excepto aquellos correspondientes a un parámetro formal.
Esto puede sercombinado con un parámetro formal de la forma *nombre que
recibe una tuplaconteniendo los argumentos posicionales además de la lista de
parámetros formales. (*nombre debe ocurrir antes de **nombre). Por ejemplo:
"""
def ventadequeso(tipo, *argumentos, **palabrasclave):
print("-- ¿Tiene", tipo,"?")
print("-- Lo siento, nos quedamos sin", tipo)
for arg in argumentos:
print(arg)
print("-" * 40)
for c in palabrasclave:
print(c, ":", palabrasclave[c])
ventadequeso("Limburger", "Es muy liquido, sr.",
"Realmente es muy muy liquido, sr.",
cliente="Juan Garau",
vendedor="Miguel Paez",
puesto="Venta de Queso")
#- ¿Tiene Limburger ?
#- Lo siento, nos quedamos sin Limburger
# Es muy liquido, sr.
# Realmente es muy muy liquido, sr.
# ----------------------------------------
# cliente : Juan Garau
# vendedor : Miguel Paez
# puesto : Venta de Queso Argentino
"""
* Listas de argumentos arbitrarios
Una función puede ser llamada con un número arbitrario de argumentos.
Estos serán organizados en una tupla.
Antes del número variable de argumentos, cero o más argumentos normales
pueden estar presentes.
"""
>>> def muchos_items(archivo, separador, *args):
... archivo.write(separador.join(args))
...
>>>
"""
* Gralmente. argumentos de cantidad variable son útilmos en la lista de
parametros formales, pq toman el remanente de argumentos q se pasan a la función.
Cualquier parametro q suceda luego del +args solo sera 'nombrado', es decir, solo
se pueden utilizar nombradros y no posicionales.
"""
concatenar("tierra", "marte", "venus")
# 'tierra/marte/venus'
concatenar("tierra", "marte", "venus", sep=" @ ")
# 'tierra @ marte @ venus'
"""
* Desempaquetando una lista de argumentos
Cuando los argumentos ya pertences a una lista o tupla, se pueden desempaquetar
para llamar una funcion que requiere argumetnoss posicionaes separados. ej. range()
espera los argumentos inicio y fin. También se puede llamar a la función con el operador
para desempaquetar argumentos de una lista o tulpa *
"""
list(range(3, 6)) # llamada normal con argumentos separados
# [3, 4, 5]
args = [3, 6]
list (range(*args)) # argumentos desempaquetados de la lista
# [3, 4, 5]
"* Los diccionarios pueden entregar argumentos nombrados con el operador **"
def loro(tension, estado='rostizado', accion='apestar'):
print("-- Este loro no va a", accion, end=' ')
print("si toca", tension, "voltios.", end=' ')
print("Está", estado, "!")
d = {"tension": "cinco mil", "estado": "demacrado", "accion": "VOLAR"}
loro(**d)
# -- Este loro no va a VOLAR si toca cinco mil voltios. Está demacrado !
# Ejemplo Funcion FIBONACCI
def fib(n):
a, b = 0, 1
for i in range(n):
a, b = b, a+b
return a
print(fib(35))
def fibo(n):
a = fib(n-1) + fib(n-2)
return a
print(fibo(35))