Funciones¶
A lo largo de las tres últimas secciones hemos ido dando la idea de que un programa no siempre tiene que ejecutarse de forma secuencial linea por linea o sentencia por sentencia.
Algunas veces parte del código que hemos escrito no se ejecutará salvo condiciones muy concretas.
Otras veces parte del código se ejecutará varias veces antes de seguir con el resto del programa.
Y otras veces tendremos una sección de código definida que podríamos necesitar ejecutar varias veces en un programa pero no sabemos cuantas veces ni donde debe de ejecutarse.
Esta última situación da lugar a un nuevo paradigma de la programación. La programación funcional.
Una función es una estructura que nos permite definir una sección de código parametrizada e identificada con un nombre.
Con esta estructura, simplemente indicando el nombre y los parámetros necesarios, se ejecutará la sección de código que encierra la función allá donde se necesite.
Sintaxis:
- def nombre_funcion([parámetros]):
- code
- return (opcional)
Ejemplo 1 | Función sin parámetros¶
numero : int = 1
def incremento() -> int:
return numero + 1
incremento()
2
Ejemplo 2 | Función con un parámetro¶
numero : int = 1
def increment(amount : int) -> int:
return numero + amount
increment(10)
11
Ejemplo 3 | Función con varios parámetros¶
def suma(a : int, b : int) -> int:
return a + b
suma(1, 1)
2
suma(2, 1)
3
suma(3, -1)
2
Ejemplo 4 | Función con parámetros por defecto¶
Caso (a) Sintáxis correcta
def suma(a : int, b : int = 1) -> int:
return a + b
suma(1, 1), suma(10)
(2, 11)
Caso (b) Los parámetros por defecto deben ir al final
def suma(a : int = 0, b : int) -> int:
return a + b
Cell In[7], line 1 def suma(a = 0, b): ^ SyntaxError: non-default argument follows default argument
Ejemplo 5 | Llamar función indicando qué valor va a qué parámetro¶
Caso (a) Da igual el orden de asignación si se especifica el nombre del parámetro al que dar un valor
def suma(a : int = 0, b : int = 1) -> int:
return a + b
suma()
1
suma(b = -1, a = 1)
0
suma(b = -10)
-10
suma(30, -10)
20
Caso (b) Especificar valor para los parámetros que no tienen valor por defecto
def suma(a : int, b : int, c : int = 1) -> int:
return a + b + c
suma(c = -10)
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) c:\Users\sergi\Documents\repos\python_course\tutoriales\04_modularidad.ipynb Cell 22 line 4 <a href='vscode-notebook-cell:/c%3A/Users/sergi/Documents/repos/python_course/tutoriales/04_modularidad.ipynb#X22sZmlsZQ%3D%3D?line=0'>1</a> def suma(a, b, c = 1): <a href='vscode-notebook-cell:/c%3A/Users/sergi/Documents/repos/python_course/tutoriales/04_modularidad.ipynb#X22sZmlsZQ%3D%3D?line=1'>2</a> return a + b + c ----> <a href='vscode-notebook-cell:/c%3A/Users/sergi/Documents/repos/python_course/tutoriales/04_modularidad.ipynb#X22sZmlsZQ%3D%3D?line=3'>4</a> suma(c = -10) TypeError: suma() missing 2 required positional arguments: 'a' and 'b'
Ejemplo 6 | Programa de geometría¶
Sin funciones
punto_1 : dict = {'x' : 1, 'y' : 1}
punto_2 : dict = {'x' : -1, 'y' : 1}
punto_3 : dict = {'x' : 10, 'y' : 11}
punto_4 : dict = {'x' : -21, 'y' : 9}
punto_5 : dict = {'x' : 0, 'y' : 0}
distancia_punto_1_punto_2 : float = ((punto_1['x'] - punto_2['x']) ** 2 + (punto_1['y'] - punto_2['y']) ** 2) ** 0.5
distancia_punto_1_punto_3 : float = ((punto_1['x'] - punto_3['x']) ** 2 + (punto_1['y'] - punto_3['y']) ** 2) ** 0.5
distancia_punto_1_punto_4 : float = ((punto_1['x'] - punto_4['x']) ** 2 + (punto_1['y'] - punto_4['y']) ** 2) ** 0.5
distancia_punto_2_punto_4 : float = ((punto_2['x'] - punto_4['x']) ** 2 + (punto_2['y'] - punto_4['y']) ** 2) ** 0.5
distancia_punto_1_punto_2, distancia_punto_1_punto_3, distancia_punto_1_punto_4, distancia_punto_2_punto_4
(2.0, 13.45362404707371, 23.40939982143925, 21.540659228538015)
Con funciones
def get_point(x : float, y : float) -> dict:
return {'x' : x, 'y' : y}
def distance(p_1 : dict, p_2 : dict) -> float:
squared_sum : float = 0
for coordinate in p_1:
squared_sum += (p_1[coordinate] - p_2[coordinate]) ** 2
return squared_sum ** 0.5
punto_1 : dict = get_point(1, 1)
punto_2 : dict = get_point(-1, 1)
punto_3 : dict = get_point(10, 11)
punto_4 : dict = get_point(-21, 9)
punto_5 : dict = get_point(0, 0)
distancia_punto_1_punto_2 : float = distance(punto_1, punto_2)
distancia_punto_1_punto_3 : float = distance(punto_1, punto_3)
distancia_punto_1_punto_4 : float = distance(punto_1, punto_4)
distancia_punto_2_punto_4 : float = distance(punto_2, punto_4)
distancia_punto_1_punto_2, distancia_punto_1_punto_3, distancia_punto_1_punto_4, distancia_punto_2_punto_4
(2.0, 13.45362404707371, 23.40939982143925, 21.540659228538015)
Ejemplo 7 | Función con número indefinido de parámetros¶
Caso (a)
def suma(*args) -> int:
suma : int = 0
for item in args:
suma += item
return suma
suma()
0
suma(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)
78
Caso (b) *args no significa pasar una lista sino valores separados por comas
def suma(*args) -> int:
suma : int = 0
for item in args:
suma += item
return suma
suma([1, 2, 3])
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) c:\Users\sergi\Documents\repos\python_course\tutoriales\04_modularidad.ipynb Cell 33 line 9 <a href='vscode-notebook-cell:/c%3A/Users/sergi/Documents/repos/python_course/tutoriales/04_modularidad.ipynb#X30sZmlsZQ%3D%3D?line=4'>5</a> suma += item <a href='vscode-notebook-cell:/c%3A/Users/sergi/Documents/repos/python_course/tutoriales/04_modularidad.ipynb#X30sZmlsZQ%3D%3D?line=6'>7</a> return suma ----> <a href='vscode-notebook-cell:/c%3A/Users/sergi/Documents/repos/python_course/tutoriales/04_modularidad.ipynb#X30sZmlsZQ%3D%3D?line=8'>9</a> suma([1, 2, 3]) c:\Users\sergi\Documents\repos\python_course\tutoriales\04_modularidad.ipynb Cell 33 line 5 <a href='vscode-notebook-cell:/c%3A/Users/sergi/Documents/repos/python_course/tutoriales/04_modularidad.ipynb#X30sZmlsZQ%3D%3D?line=1'>2</a> suma = 0 <a href='vscode-notebook-cell:/c%3A/Users/sergi/Documents/repos/python_course/tutoriales/04_modularidad.ipynb#X30sZmlsZQ%3D%3D?line=3'>4</a> for item in args: ----> <a href='vscode-notebook-cell:/c%3A/Users/sergi/Documents/repos/python_course/tutoriales/04_modularidad.ipynb#X30sZmlsZQ%3D%3D?line=4'>5</a> suma += item <a href='vscode-notebook-cell:/c%3A/Users/sergi/Documents/repos/python_course/tutoriales/04_modularidad.ipynb#X30sZmlsZQ%3D%3D?line=6'>7</a> return suma TypeError: unsupported operand type(s) for +=: 'int' and 'list'
Ejemplo 8 | Función con número indefinido de parámetros pero cada uno con un nombre¶
def foo(**kwargs) -> dict:
return kwargs
foo(a = 1, b = 2, c = 3, d = 4)
{'a': 1, 'b': 2, 'c': 3, 'd': 4}
Extra 1 | Definir 2 funciones con mismo nombre implica que solo la última definición tiene efecto¶
def suma(a : int = 0, b : int = 1) -> int:
return a + b
def suma(a : int = 0, b : int = 1) -> int:
return a * a + b * b
suma(2, 2)
8
Extra 2 | Combinación arg, *kwargs y parámetros con nombre específicos¶
def foo(a : int, *args, **kwargs) -> tuple:
return a, args, kwargs
foo(1, 2, b = 'a')
(1, (2,), {'b': 'a'})
Extra 3 | Funciones anónimas¶
A veces tendremos funciones cuyo código encapsulado solo ocupa una sentencia de return expresion.
Es decir, tendremos funciones que hacer un pequeño computo e inmediatamente devuelven el resultado.
Un ejemplo sería la función suma con la que hemos trabajado en muchos ejemplos.
Esta recibe una serie de parámetros, los suma y devuelve esa suma.
- def suma(a, b):
- return a + b
Cuando tengamos este tipo de funciones sencillas, podemos directamente hacer uso de lo que se conoce como funciones lambda.
Sintaxis:
- lambda param1, param2 : code
Esta función se guarda en una variable, recibe los parametros especificados, realiza el cómputo especificado y devuelve el resultado de manera implícita.
Se usa de la misma forma que las funciones def. No deja de ser una funcion solo que con una sintaxis más compacta.
# Función sin lambda
def suma_sin_lambda(a : int, b : int) -> int:
return a + b
# Función con lambda
suma_con_lambda = lambda a, b : a + b
suma_sin_lambda(1, 2), suma_con_lambda(1, 2)
(3, 3)
Extra 4 | Funciones built-in o funciones disponibles por defecto en cualquier archivo de python¶
Por defecto, tenemos a nuestra disposición un gran variedad de funciones que podemos usar en cualquier momento.
Algunas de las que más se suelen usar son:
- abs(x)
- min(*args)
- max(*args)
- int(object)
- float(object)
- list(object)
- tuple(object)
- set(object)
- dict(object)
- str(object)
- bool(object)
- type(object)
- print(*objects, sep = ' ', end = '\n', file = sys.stdout, flush = False)
- help(object = None)
- zip(*iterables)
- enumerate(iterable)
- range(start, stop, step = 1)
- len(iterable)
abs(), min(), max()¶
Son operaciones matématicas básicas:
- abs(x) Devuelve el valor absoluto de un númeno
- min(*args) Devuelve el valor mínimo de una serie de números pasados a la función separados por comas
- max(*args) Devuelve el valor máximo de una serie de números pasados a la función separados por comas
abs(-1)
1
min(0, -1, -30, 20)
-30
max(0, -1, -30, 40)
40
type(), int(), float(), bool(), str(), list(), tuple(), dict(), set()¶
Estas funciones nos permiten trabajar con los tipos de datos:
- type() Devuelve el tipo de dato de una variable, ...
- int() Trata de convertir una variable en entero
- float() Trata de convertir una variable en float
- bool() Trata de convertir una variable en bool
- str() Trata de convertir una variable en string
- list() Trata de convertir una variable en list | Se suele usar con tuplas
- tuple() Trata de convertir una variable en tuple | Se suele usar con listas
- dict() Trata de convertir una variable en dict | Necesario lista de lista. [ [1, 2] ] -> {1 : 2}
- set() Trata de convertir una variable en set | Se suele usar con listas y tuplas
type(1)
int
type([1,])
list
int(1.634)
1
float(-1)
-1.0
bool([1, 2])
True
str([{1, 3}, 1])
'[{1, 3}, 1]'
list((1, 2))
[1, 2]
tuple([1, 2])
(1, 2)
dict([['a', 2], ['b', 4]])
{'a': 2, 'b': 4}
set([1, 2, 3, 1])
{1, 2, 3}
print()¶
No permite mostrar texto por pantalla o guardar texto en archivos
print(1)
print(1, 2, 3, sep = '|||')
print('aa', end = '--------------------------------')
print([])
1 1|||2|||3 aa--------------------------------[]
help()¶
Normalmente las funciones y otros códigos tienen una documentación. Es decir, una parte del código de la función es una serie de comentarios explicando qué hace esa función. Con help() podemos acceder a esa documentación.
def foo() -> None:
"""Función estúpida. No hace nada.
"""
help(foo)
Help on function foo in module __main__:
foo()
Función estúpida. No hace nada.
zip()¶
Algunas veces suele pasar que tenemos 2 o más variables de tipo secuencia (Ej : lista) y necesitamos trabajar cada valor de en paralelo.
Es decir, si trabajamos con el primer elemento, queremos trabajar con los primeros elementos de todas las secuencias a la vez y así con el resto de elementos.
"""
Código que dadas dos listas, genera una con la suma de cada pareja
"""
lista1 : list = [1, 2, 3]
lista2 : list = [2, 3, 4]
suma_lista1_lista2 : list = []
for pareja in zip(lista1, lista2):
suma_lista1_lista2.append(sum(pareja)) # append es una función de la variable lista | la veremos en otras secciones
suma_lista1_lista2
[3, 5, 7]
enumerate()¶
A veces, cuando trabajamos con secuencias, necesitamos saber cual en qué posición estamos. Es decir, trabajamos con ¿estamos trabajando con el primer elemento, el segundo, ...?
La función enumerate(sequence) devuele una pareja (índice, valor)
lista : list = [1, 2, 3, 4, 5]
for indice, valor in enumerate(lista):
print('Accediendo al valor', valor, 'en la posición', indice, 'de la lista', lista)
Accediendo al valor 1 en la posición 0 de la lista [1, 2, 3, 4, 5] Accediendo al valor 2 en la posición 1 de la lista [1, 2, 3, 4, 5] Accediendo al valor 3 en la posición 2 de la lista [1, 2, 3, 4, 5] Accediendo al valor 4 en la posición 3 de la lista [1, 2, 3, 4, 5] Accediendo al valor 5 en la posición 4 de la lista [1, 2, 3, 4, 5]
"""
Código que recorre una lista.
Calcula en cuadrado del valor actual y lo pone de nuevo en la lista.
"""
lista : list = [1, 2, 3, 4, 5, 6, 7, 8, 9]
for indice, valor in enumerate(lista):
lista[indice] = valor ** 2
lista
[1, 4, 9, 16, 25, 36, 49, 64, 81]
range()¶
Hemos visto en muchos ejemplo que las lista numéricas suelen ser de la forma [1, 2, 3, ...].
Cuando tenemos una lista de número con un patrón concreto, en vez de crear la lista manualmente, podemos hacer uso de la función range.
print(list(range(0, 10, 1)))
print(list(range(0, 10, 2)))
print(list(range(-10, 10, 2)))
print(list(range(10, -10, -2)))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] [0, 2, 4, 6, 8] [-10, -8, -6, -4, -2, 0, 2, 4, 6, 8] [10, 8, 6, 4, 2, 0, -2, -4, -6, -8]
len(iterable)¶
Devuelve la cantidad de elementos de un dato iterable.
print( len([1, 2, 3, 4, 5, 6, 7, 8, 9]) )
print( len({'a' : 1, 'b' : -1}) )
9 2
Ejercicios¶
- Crea una función que dada una lista de números enteros como parámetro
- Devuelva una lista nueva con los números impares de la misma
- Crea una función que dada una lista de números enteros como parámetro
- Devuelva una lista nueva con los números pares de la misma
- Crea una función que dada una lista de números enteros como parámetro
- Devuelva una lista con todos números que sea distintos (que no se repitan)
- Crea una función que dada una lista de números enteros como parámetro
- Devuelva el porcentaje de números que no están repetidos (solo aparecen una vez en la lista)