Python Avanzado

Introducción

Funciones

Estructura de una función


# Función cálculo del área de un cuadrado 1 "Doc string (comentario colocando "#" al inicio de la línea)"

def calcular_area_cuadrado_1(lado):
  area = lado * lado
  return area

#Función para calcular el perímetro de un cuadrilátero

def calcular_perimetro(lado_1, lado_2, lado_3, lado_4):
  perimetro = lado_1 + lado_2 + lado_3 + lado_4
  return perimetro

Definiciones:

- Parámetro: Nombre de la variable

- Argumento: Valor del parámetro invocado

- “* args”: Non keywords arguments, parámetros especiales para pasar parámetros opcionales en forma de lista

- “* * kwargs”: keywords arguments, parámetros especiales para pasar parámetros opcionales en forma de diccionario

- Retorno: Es el que regresa la función como resultado del proceso

Uso del parámetro “* args”


#Función para calcular el perímetro de cualquier polígono, uso de "*args" (los parámetros se listan en un listado de tipo tupple)

def calcular_perimetro_args(*args):
  print(args) # Para ver qué trae args al ejecutarse la función
  perimetro = 0
  
  for lado in args:
    perimetro += lado
  
  return perimetro

#Aplicando función cálculo área cuadrado 1

area_cuadrado = calcular_area_cuadrado_1(lado = 5)

print(area_cuadrado)

#Aplicando función cálculo de perímetro de un cuadrilátero
## 25
perimetro_1 = calcular_perimetro(1, 2, 3, 4)
print(perimetro_1)
## 10
perimetro_2 = calcular_perimetro_args(1, 2, 3, 4, 5)
## (1, 2, 3, 4, 5)
print(perimetro_2)
## 15

Uso del parámetro “* * kwargs”


# Funciones utilizando el parámetro "**kwargs"

def funcion_kwargs_1(**kwargs):
  print(kwargs) # Para ver qué trae kwargs al ejecutarse la función (los parámetros se listan en un listado de tipo diccionario)

# Aplicando la función creada usando el parámetro "**kwargs"

funcion_kwargs_1(nombre = "Paco")

# Funciones utilizando el parámetro "**kwargs" con más de una llave y valor
## {'nombre': 'Paco'}
def funcion_kwargs_2(**kwargs):
  print(kwargs) # Para ver qué trae kwargs al ejecutarse la función (los parámetros se listan en un listado de tipo diccionario)
  for llave, valor in kwargs.items():
    print(f"llave: {llave}, valor: {valor}")
  print(kwargs["nombre"], kwargs["apellido"]) # Esto se puede realizar por el tipo del dato kwargs que es diccionario

# Aplicando la función creada usando el parámetro "**kwargs"

funcion_kwargs_1(nombre = "Paco")
## {'nombre': 'Paco'}
funcion_kwargs_2(nombre = "Paco", apellido = "Botero")
## {'nombre': 'Paco', 'apellido': 'Botero'}
## llave: nombre, valor: Paco
## llave: apellido, valor: Botero
## Paco Botero

Usando los tres parámetros permitidos en una función


# Uso de todos los parámetros permitidos en la definición de una función

def parametros_ordenados_1(nombre, apellido, *args, **kargs):
  pass # Este código es para que no salga error al probar lo hasta ahora realizado

#def parametros_desordenados_1(nombre, apellido, **kwargs, *args):
#  pass # Aquí se nos mostrará un error de syntaxis pues el orden de los parámetros colocados en la función es incorrecto. En python se debe guardar el orden

Cálculo Lambda en Python

El cálculo lambda es un lenguaje basado en la abstracción creado en 1930 por Alonzo Church considerado minimalista ya que es una expresión sensilla en una sola línea.

Es una programación basada en funciones y puede tomar uno o más argumentos.

La estructura del código que define la función lambda es:

lambda “argumento”: “expresión”

- lambda –> sentencia que invoca la función

- “argumento” –> variable dependiente

- : –> la expresión de la función

- “expresión” –> el cuerpo de la función, expresión que la define

Las funciones anónimas no se definen con “def”, éstas tienen diferentes nombres según el lenguaje de programación utilizado. Pueden ser:

- Expresiones anónimas

- Expresiones lambda

- Funciones lambda, entre otras

En Python se conocen como Funciones Lambda y se utilizan para expresiones simples y que no se repitan mucho en el código.

Para invocar la función lambda definida se edita lo siguiente:

**“_(argumento,)“**


# Definiendo una función anónima en python

#lambda num: num*2

#_(2,)

# La anterior definición no es práctica, la siguiente sí lo es ya que no se espera indicar el valor a cálcular en una segunda línea

(lambda num: num*2)(2,)

# Asignando a una variable la función anónima lambda
## 4
multiplicacion = lambda num: num*2

multiplicacion(2)
## 4

Diferencias entre Funciones y Funciones Lambda


# Función separar números pares e impares. Ésta función no es simple por lo que no podría convertirse a una función lambda

def separar_par_impar(lista_numeros):
  pares = []
  impares = []
  for numero in lista_numeros:
    if numero %2 == 0:
      pares.append(numero)
    else:
      impares.append(numero)
  return pares, impares

# Función cálculo del área de un cuadrado 2. Ésta función sí es simple por lo que se puede transformar a una función lambda

def calcular_area_cuadrado_2(lado):
  return lado ** 2

# Función lambda de la función del cálculo del área de un cuadrado

calcular_cuadrado = lambda lado: lado ** 2

print(calcular_cuadrado(2))
## 4

Casos de uso de la función lambda


lista_numeros = [1, 2, 3, 4, 5, 6, 7, 8]

# Utilizando la función lambda

lista_pares = lambda numero: numero %2 == 0
print(lista_pares(3))

# Utilizando la función filter en la expresión anterior
## False
lista_pares = list(filter(lambda numero: numero %2 == 0, lista_numeros))
print(lista_pares) # La función list convierte el objeto filter en una lista para poder ser mostrada con el print

# Utilizando la función map
## [2, 4, 6, 8]
nueva_lista = list(map(lambda numero: numero * 10, lista_numeros))
print(nueva_lista) # Nuevamente la función list convierte el objeto map en una lista para poder ser mostrada con el print
## [10, 20, 30, 40, 50, 60, 70, 80]

Según el convenio de uso en Python no es recomendable utilizar las funciones lambda en exceso en nuestros códigos.

Iterables e Iteradores

Los iterables, características:

- Conjuntos de elementos

- Retornan los elementos que lo componen

- Se recorren usando ciclos

Los tipos de datos en python que se pueden iterar son:

- Cadenas de texto

- Listas

- Tuplas

- Diccionarios

Los iteradores, características:

- Son objetos

- Permiten recorrer un objeto iterable

Funciones nativas en Python para iterar

Son dos las funciones nativas en python que permiten iterar sin utilizar ciclos:

- Función iter(): permite recorrer el iterable

- Función next(): retorna el elemento siguiente en el iterable


# Usando funciones nativas iter() y next()

numeros = [1, 2, 3]

iterador = iter(numeros) # Se crea un tipo list_iterator

iterador
## <list_iterator object at 0x00000157A3B0D340>
next(iterador) # Con la función next() se mostrará el siguiente valor del objeto "numero" (el primer elemento 1)
## 1
next(iterador) # Si volvemos a usarlo mostrará el siguiente número en lista (2)
## 2
next(iterador) # Una tercera vez mostrará el siguiente y último valor en lista para este caso (3)

#next(iterador) # Si usamos una vez más la función next() y al haber estado antes en el último valor de la lista, nos arrojará un error en el resultado

# Traceback (most recent call last):
#   File "<stdin>, lin 1, in <module>
# StopIteration:
## 3

Las funciones iter() y next() se utilizan como base para otras funciones como zip(), map() ó filter()

Ciclos For

Los ciclos For se pueden realizar sobre objetos:

-Listas

-Diccionarios

Comparando lenguajes

Ciclos for en otros lenguajes

for (inicializador; condición; iterador){

instrucción

}

Ciclo for en JS

let nombres = [“Paco”, “Emilio”, “Javier”]

for (let i = 0; i < nombres.length; i += 1){

console.log(nombres[i]) # Imprimir la posición i de la lista nombres

}

Ciclo for en Python

for elemento in list:

instruction

Aunque en Python no se tiene una estructura tradicional al realizar el ciclo for, sí existen funciones que al utilizarlas durante la declaración del ciclo hacen que se asemeje a una declaración tradicional del ciclo for


# Ejemplo de ciclo for

nombres_1 = ["Paco", "Emilio", "Javier"]

for elemento_1 in nombres_1:
  print(elemento_1)
## Paco
## Emilio
## Javier

Existen palabras reservadas que se pueden utilizar durante la declaración de un ciclo for:

- break

- continue


# Rompiendo un ciclo for

nombres = ["Paco", "Emilio", "Javier"]

for elemento in nombres:
  if elemento == "Emilio":
    break # Con ésta sentencia el ciclo se rompe
  print(elemento)

# Saltando un valor en un ciclo
## Paco
for elemento in nombres:
  if elemento == "Emilio":
    continue # Con ésta sentencia el ciclo se salta un valor, continúa con la siguiente iteración
  print(elemento)

# Si no utilizamos una condición para incluir la función break
## Paco
## Javier
for elemento in nombres:
  print(elemento)
  break # Aquí el ciclo se rompe luego de la primera iteración

# Si no utilizamos una condición para incluir la función continue
## Paco
for elemento in nombres:
  print(elemento)
  continue # Aquí el ciclo no se salta ninguna iteración
## Paco
## Emilio
## Javier
for elemento in nombres:
  continue # Aquí el ciclo se salta todas las iteraciones
  print(elemento)

Función range()

Crea una serie de números consecutivos o no, en este último se puede indicar el incremento o decremento a darse entre número y número

La función permite declarar:

- inicio: Valor inicial del rango a crear, por default “0”

- fin: Valor final del rango a crear (valor_final = fin - 1)

- paso: Valor del incremento o decremento a realizar para la creación del rango, por default “1”

Se declara como:

range(inicio, fin, paso)


# Usando la función range()

serie_1 = range(5) # Si colocamos un solo argumento, es el fin
print(list(serie_1)) # list muestra los valores del rango y no el rango
## [0, 1, 2, 3, 4]
serie_2 = range(5, 10) # Si colocamos dos argumentos, es el inicio y fin
print(list(serie_2))
## [5, 6, 7, 8, 9]
serie_3 = range(3, 10, 2) # Se colocan todos los argumentos
print(list(serie_3))

# Iterando sobre cada uno de los elementos de la serie
## [3, 5, 7, 9]
for elemento in serie_3:
  print(elemento)
## 3
## 5
## 7
## 9

Escribiendo algunos códigos


lista_num = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# Realizando una lista de números al cuadrado, versión extendida

lista_cuadrados = []

for num in lista_num:
  cuadrado = num ** 2
  lista_cuadrados.append(cuadrado)

print("Ciclo for", lista_cuadrados)

# Realizando una lista de números al cuadrado, versión comprimida
## Ciclo for [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
lista_comprehension = [num ** 2 for num in lista_num]

print("Lista comprehensión", lista_comprehension)
## Lista comprehensión [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]