Programación en Python
Programación en Python
Introducción a Python
Como hemos aprendido, en la era digital actual, los datos son omnipresentes y fundamentales
para la toma de decisiones en diversas industrias. Desde el análisis de tendencias de mercado
hasta la optimización de procesos empresariales, la ciencia de datos desempeña un papel crucial
en la generación de ideas y la resolución de problemas.
Amplia variedad de bibliotecas: ofrece una amplia gama de bibliotecas especializadas en ciencia
de datos, como NumPy, Pandas, Matplotlib y SciPy, que facilitan tareas como la manipulación de
datos, el análisis estadístico y la visualización.
Comunidad activa: cuenta con una comunidad activa y colaborativa que constantemente
desarrolla nuevas herramientas y comparte recursos educativos, lo que facilita el aprendizaje y la
resolución de problemas.
Flexibilidad: es un lenguaje versátil que se puede utilizar en una variedad de contextos, desde
análisis de datos hasta desarrollo web y automatización de tareas.
¡Comencemos!
Unidad 1
Tema 1. Tipos de datos en Python
Una variable es la estructura de datos más simple que podemos encontrar. Es un espacio de
memoria donde guardamos un dato, y a la vez, ese espacio de memoria recibe un nombre.
Podemos imaginarla como un contenedor o una caja donde se guardan objetos. Estos objetos
pueden estar en formato texto, número, etc.
Las variables poseen un nombre llamado identificador. Es como ponerle un nombre a la caja con
alguna etiqueta.
Para nombrar las variables existen ciertas reglas:
Figura 1. Ejemplo
Fuente: elaboración propia.
Figura 2. Ejemplo
Fuente: elaboración propia.
Ejemplo: la expresión "x > 0 and y < 10" será verdadera si la variable "x" es mayor que cero y la
variable "y" es menor que diez. Si cualquiera de estas condiciones no se cumple, el resultado será
falso.
Figura 3. Ejemplo
Or se utiliza para realizar una operación de disyunción lógica entre dos expresiones booleanas. Si
al menos una de las expresiones es verdadera (true), el resultado de la operación es verdadero
(true), de lo contrario, si ambas expresiones son falsas (false), el resultado será falso (false). Por
ejemplo, la expresión "x > 0 or y < 10" será verdadera si la variable "x" es mayor que cero o la
variable "y" es menor que diez. Si ambas condiciones no se cumplen, el resultado será falso.
Figura 4. Ejemplo
Xor (o or exclusivo) se utiliza para realizar una operación de disyunción exclusiva lógica entre dos
expresiones booleanas. Si exactamente una de las expresiones es verdadera (true), el resultado
de la operación es verdadero (true), de lo contrario, si ambas expresiones son verdaderas o
ambas son falsas, el resultado será falso (false).
¡Veamos los conceptos en la práctica!
Descarga el notebook haciendo clic aquí y mira el video explicativo.
Por ejemplo, si queremos convertir un valor numérico almacenado como cadena en un valor
entero, podemos utilizar la función "int()" para realizar la conversión. Del mismo modo, si
queremos convertir un valor numérico en un valor de punto flotante, podemos utilizar la función
"float()".
Para convertir un número binario a su equivalente decimal, se multiplican los dígitos binarios por
sus respectivas potencias de 2 y se suman los resultados. En el ejemplo anterior, el número
binario 1101 se convierte a decimal de la siguiente manera:
(1 * 2^3) + (1 * 2^2) + (0 * 2^1) + (1 * 2^0) = 8 + 4 + 0 + 1 = 13
En la programación, los números binarios se utilizan en operaciones de bits para realizar
manipulaciones eficientes en los datos. Estas operaciones pueden incluir desplazamientos,
combinaciones lógicas (como and, or, xor) y manipulaciones más complejas utilizando las
propiedades de los bits. Los números binarios son esenciales en el procesamiento de datos
porque proporcionan una forma eficiente y confiable de representar, almacenar, procesar y
comunicar información en sistemas digitales y computadoras.
Operaciones
Una de las operaciones de bits comunes en Python es el desplazamiento a la izquierda de bits
(<<). Esta operación desplaza los bits de un número hacia la izquierda en una cantidad específica
de posiciones y rellena los espacios vacíos con ceros.
Por ejemplo, consideremos la operación 1 << 2 en Python. El número binario 1 se desplaza dos
posiciones hacia la izquierda y se rellena con ceros a la derecha. El resultado de esta operación
es 4.
Aquí está el proceso paso a paso de la operación 1 << 2.
El número 1 en binario se representa como 0001.
Aplicamos el desplazamiento de dos posiciones hacia la izquierda a 0001, lo que resulta en 0100.
resultado = 1 << 2
print(resultado)
4
Flujos de control
Los flujos de control son la forma en que podemos controlar el flujo de ejecución de un programa,
lo que nos permite tomar decisiones y repetir acciones en función de diferentes condiciones. Con
los flujos de control, podemos hacer que un programa sea más dinámico y adaptable, y, lo mejor
de esto, es que Python ofrece una gran variedad de herramientas para hacerlo de manera fácil y
sencilla.
Un condicional es una estructura de control de flujo en Python que nos permite tomar decisiones y
ejecutar diferentes acciones en función de si se cumple una condición o no. En otras palabras, los
condicionales son una forma de programar diferentes resultados basados en ciertas condiciones
En Python, los condicionales se crean utilizando la palabra clave if seguida de una expresión
booleana, seguida de un bloque de código que se ejecutará si la expresión booleana es
verdadera (true). También se pueden utilizar otras palabras clave, como elif y else para ejecutar
diferentes bloques de código en función de diferentes condiciones.
Ejemplo:
a=5
b=7
if a < b:
print('a es menor que b')
elif a > b:
print('a es mayor que b')
else:
print('a y b son iguales')
¡Veamos los conceptos en la práctica!
Descarga el notebook haciendo clic aquí y mira el video explicativo.
El ciclo for, en Python, se utiliza para iterar sobre una secuencia (como una lista, tupla, conjunto o
cadena de texto) o cualquier objeto iterable. Itera sobre cada elemento de la secuencia y ejecuta
un bloque de código para cada uno de ellos.
Su sintaxis es la siguiente:
for <elemento> in <elementos a iterar>:
<Tu código>
Se coloca la sentencia for seguida de la variable donde se almacenarán los ítems y luego del
operador in el elemento a iterar.
for e in son palabras reservadas del bucle for.
Ejemplo:
numeros = [1,2,3,4,5]
for num in numeros:
suma= num+1
print(suma)
while
Estructura de control de flujo que se utiliza para repetir una acción mientras se cumpla una
condición específica. El bucle while ejecuta un bloque de código mientras la expresión booleana
especificada en la cabecera del bucle sea verdadera (true), lo que nos permite realizar tareas
repetitivas hasta que se cumpla una determinada condición.
Su sintaxis es la siguiente:
while expresión_booleana:
# bloque de código a ejecutar mientras la expresión sea verdadera
En la primera línea, se utiliza la palabra clave while para indicar que se está creando un bucle
while. Luego, se escribe una expresión booleana que se evalúa como verdadera o falsa. Si la
expresión es verdadera, el bloque de código indentado que sigue se ejecutará una y otra vez
hasta que la expresión sea falsa.
El bloque de código que se ejecuta dentro del bucle puede incluir cualquier cantidad de líneas de
código, siempre y cuando estén indentadas (desplazadas a la derecha). Es importante tener en
cuenta que, si la expresión booleana nunca se vuelve falsa, el bucle se ejecutará infinitamente, lo
que puede causar problemas en el programa. Por lo tanto, es importante asegurarse de que haya
una condición en el bloque de código que permita salir del bucle eventualmente.
Ejemplo de ciclo while:
num = 1
while num < 6:
print("El número es ", num)
num =num +1
Ambas sentencias se utilizan en bucles (como los bucles while o for) para modificar el
comportamiento del programa en ciertas situaciones.
Sentencia break
La sentencia break permite alterar el comportamiento de los bucles while y for. Concretamente,
nos permite terminar con la ejecución del bucle. Esto significa que una vez se encuentra la
palabra break, el bucle se habrá terminado.
Ejemplos:
cadena = 'Python'
for letra in cadena:
if letra == 'h':
print("Se encontró la h")
break
print(letra)
x=5
while True:
x -= 1
print(x)
if x == 0:
break
print("Fin del bucle")
Sentencia continue
Al igual que el ya visto break, permite modificar el comportamiento de los bucles while y for.
Concretamente, la sentencia continue se salta todo el código restante en la iteración actual y
vuelve al principio en el caso de que aún queden iteraciones por completar.
Ejemplo:
cadena = 'Python'
for letra in cadena:
if letra == 'P':
continue
print(letra)
Las listas son estructuras de datos que pueden almacenar cualquier otro tipo de dato, inclusive
una lista puede contener otra lista, además, la cantidad de elementos de una lista se puede
modificar removiendo o añadiendo elementos. Para definir una lista se utilizan los corchetes,
dentro de estos se colocan todos los elementos separados por comas.
calificaciones = [10,9,8,7.5,9]
nombres = ["Ana","Juan","Sofía","Pablo","Tania"]
Las listas son iterables y, por tanto, se puede acceder a sus elementos mediante indexación:
nombres[2]
'Sofía'
nombres[-1]
'Tania'
Tuplas (tuple)
Las tuplas son secuencias de elementos similares a las listas, pero se diferencian en que no
pueden ser modificadas directamente. Es decir, una tupla no dispone de los métodos como
append o insert que modifican los elementos de una lista.
Para definir una tupla, los elementos se separan con comas y se encierran entre paréntesis.
colores=("Azul","Verde","Rojo","Amarillo","Blanco","Negro","Gris")
Las tuplas al ser iterables pueden accederse mediante la notación de corchetes e índice. Por
ejemplo:
colores[0]
'Azul'
colores[-1]
'Gris'
colores[3]
'Amarillo'
Si intentamos modificar alguno de los elementos de la tupla Python nos devolverá un TypeError:
colores[0] = "Café"
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-96-3502c7127536> in <module>()
----> 1 colores[0] = "Café"
Los diccionarios son estructuras que contienen una colección de elementos de la forma clave:
valores separados por comas y encerrados entre llaves. Las claves deben ser objetos inmutables
y los valores pueden ser de cualquier tipo. Necesariamente las claves deben ser únicas en cada
diccionario, no así los valores.
Vamos a definir un diccionario llamado edades en el cual cada clave será un nombre y el valor
una edad:
edades = {"Ana": 25, "David": 18, "Lucas": 35, "Ximena": 30, "Ale": 20}
Puede acceder a cada valor de un diccionario mediante su clave, por ejemplo, si quisiéramos
obtener la edad de la clave Lucas se tendría que escribir:
edades["Lucas"]
35
Iteradores
Un iterador es un objeto que devuelve una secuencia de valores uno a uno. Pueden ser de
longitud finita o de longitud infinita (aunque la mayoría de iteradores orientados a contenedores
proporcionan un conjunto fijo de valores).
Por ejemplo, se puede emplear un ciclo while para recorrer los elementos de una lista y
agregarlos a otra lista.
print(list(c))
# [(1, 'Uno'), (2, 'Dos')]
# 1 Uno
# 2 Dos
Deshacer el zip()
Con un pequeño truco, es posible deshacer el zip en una sola línea de código. Supongamos que
hemos usado zip para obtener c.
a = [1, 2, 3]
b = ["One", "Two", "Three"]
c = zip(a, b)
print(list(c))
# [(1, 'One'), (2, 'Two'), (3, 'Three')]
print(a) # (1, 2, 3)
print(b) # ('One', 'Two', 'Three')
out: 4
Recuerda, para seguir paso a paso los ejemplos, descarga el notebook haciendo clic aquí.
Tema 6. Funciones
Se puede entender una función como un conjunto de líneas de código que realizan una tarea
específica y pueden tomar argumentos para diferentes parámetros que modifiquen su
funcionamiento y los datos de salida. Una función te permite implementar operaciones que son
habitualmente utilizadas en un programa y, de esta manera, reducir la cantidad de código.
Las funciones en Python son una parte del código de nuestro programa que se encargan de
cumplir algún objetivo específico definido por nosotros o por el lenguaje, recibiendo ciertos datos
de entrada (argumentos) en los llamados parámetros para procesarlos y brindarnos datos de
salida o de retorno.
Las funciones en Python son componentes importantes en la programación y cuentan con una
estructura que consta de dos principios:
Principio de reutilización: puedes reutilizar una función varias veces y en distintos programas.
Principio de modularización: te permite segmentar programas complejos con módulos más
simples para depurar y programar con mayor facilidad.
Ejemplo:
def di_hola(): # definimos la función di_hola
print('Hola')
salida:
Buen día Juan
Las variables dentro de las funciones tienen un alcance local, lo que significa que solo pueden ser
accedidas dentro de la función donde fueron definidas. En contraste, las variables definidas fuera
de las funciones tienen un alcance global y pueden ser utilizadas en cualquier parte del código. Si
se necesita acceder a una variable local desde fuera de la función, se puede utilizar la palabra
reservada global seguida del nombre de la variable. Es importante tener en cuenta que no se
puede declarar e inicializar una variable global en una misma línea, sino que se debe hacer en
dos líneas separadas, como se muestra en el siguiente ejemplo:
def funcion1():
global num1
num1 = 10
funcion1()
print(num1)
El alcance de una variable determina en qué partes del código se puede acceder a ella y es
crucial cuando se trabaja en proyectos grandes y complejos en los que se utilizan múltiples
funciones y archivos. En estos casos, es importante tener en cuenta el alcance de una variable
para evitar errores y comportamientos inesperados.
Por ejemplo, si definimos una variable global en el archivo principal de nuestro proyecto y la
queremos utilizar en una función, podemos hacerlo sin problemas. Sin embargo, si definimos una
variable local con el mismo nombre dentro de esta función, Python utilizará la variable local en
lugar de la global. Esto puede llevar a comportamientos inesperados y errores difíciles de
detectar.
# Definimos una variable global
nombre = "Juan"
# Creamos una función que define una variable local con el mismo nombre
def saludo():
nombre = "Maria"
print("Hola " + nombre)
# Llamamos a la función
saludo()
Recursividad
La recursividad o recursión es un concepto que proviene de las matemáticas, y que aplicado al
mundo de la programación nos permite resolver problemas o tareas, dividiéndolas en subtareas
con la misma funcionalidad. Dada la lógica de que los subproblemas a resolver son de la misma
naturaleza, se puede usar la misma función para resolverlos. Dicho de otra manera, una función
recursiva es aquella que está definida en función de sí misma, por lo que se llama repetidamente
a sí misma hasta llegar a un punto de salida.
Por otro lado, tiene que existir siempre una condición en la que la función retorna sin volver a
llamarse. Es muy importante porque de lo contrario, la función se llamaría de manera indefinida.
Calcular factorial
Uno de los ejemplos más usados para entender la recursividad, es el cálculo del factorial de un
número n!.
factorial_normal(5)
out: 120
Dado que el factorial es una tarea que puede ser dividida en subtareas del mismo tipo
(multiplicaciones), podemos darle un enfoque recursivo y escribir la función de la siguiente
manera:
def factorial_recursivo(n):
if n == 1:
return 1
else:
return n * factorial_recursivo(n-1)
factorial_recursivo(5)
out: 120
Lo que realmente hacemos con el código anterior es llamar a la función factorial_recursivo()
múltiples veces. Es decir, 5! es igual a 5 * 4! y 4! es igual a 4 * 3! y así sucesivamente hasta llegar
a 1.
Algo muy importante a tener en cuenta es que si realizamos demasiadas llamadas a la función,
podríamos llegar a tener un error del tipo RecursionError. Esto se debe a que todas las llamadas
van apilándose y creando un contexto de ejecución, algo que podría llegar a causar un stack
overflow. Es por eso por lo que Python lanza ese error, para protegernos de llegar a ese punto.
Tradicionalmente:
Los tipos simples se pasan por valor: enteros, flotantes, cadenas, lógicos, etc.
Los tipos compuestos se pasan por referencia: listas, diccionarios, conjuntos, etc.
n = 10
doblar_valor(n)
print(n)
10
ns = [10,50,100]
doblar_valores(ns)
print(ns)
n = 10
n = doblar_valor(n)
print(n)
20
Y en el caso de los tipos compuestos, podemos evitar la modificación enviando una copia:
def doblar_valores(numeros):
for i,n in enumerate(numeros):
numeros[i] *= 2
ns = [10,50,100]
doblar_valores(ns[:]) # Una copia al vuelo de una lista con [:]
print(ns)
Funciones lambda
Es una subrutina definida que no está enlazada a un identificador. Las expresiones lambda a
menudo son argumentos que se pasan a funciones de orden superior o se usan para construir el
resultado de una función de orden superior que necesita devolver una función. Si la función solo
se usa una vez o un número limitado de veces, una expresión lambda puede ser sintácticamente
más simple que usar una función con nombre.
En Python, las lambdas son funciones anónimas (debemos evitar asignarlas a una variable). Las
funciones lambdas tienen una sintaxis concisa y pueden utilizarse con otras funciones
incorporadas de gran ayuda.
def cuadrado(num):
return num*num
Creamos una versión lambda de esta:
>>> (lambda num: num*num)(2)
Clases
Las clases, por lo tanto, son plantillas o proyectos dentro de las que se guardan los objetos. Estas
proporcionan un medio para agrupar datos y funcionalidades distintas.
Las clases no son objetos en Python como tal, sino que albergan a estos objetos. No obstante, la
creación de una nueva clase crea un nuevo tipo de objeto, lo que permite crear nuevas instancias
de ese tipo.
Objetos
Los objetos son aquellas instancias que van dentro de una clase, esto es, cualquier elemento
dentro de esta. Cada una de estas instancias u objetos tiene unos atributos definidos para
conservar su estado.
Asimismo, cada una de las instancias y clases pueden tener métodos dentro, definidos por su
misma clase, para modificar su estado.
Así pues, una clase es como un modelo o categoría, mientras que un objeto o instancia es una
copia de la clase con valores reales.
Identidad: es el nombre único de un objeto y permite que este interactúe con otros.
Métodos
Los métodos son funciones que están definidas dentro de una clase y operan sobre los atributos
de esta, al tiempo que permiten definir las funcionalidades o responsabilidades de la clase.
El objetivo de un método dentro de las clases y objetos en Python es ejecutar las actividades que
tiene encomendadas la clase a la que pertenece.
Los atributos de un objeto se modifican mediante un llamado a sus métodos.
Herencia
La herencia es un proceso mediante el cual se puede crear una clase hija que hereda de una
clase padre, compartiendo sus métodos y atributos. Además de ello, una clase hija puede
sobrescribir los métodos o atributos o incluso definir unos nuevos.
Se puede crear una clase hija con tan solo pasar como parámetro la clase de la que queremos
heredar. En el siguiente ejemplo vemos cómo se puede usar la herencia en Python, con la clase
“Perro” que hereda de “Animal”.
class Animal:
def __init__(self, nombre, edad):
self.nombre = nombre
self.edad = edad
def hacer_sonido(self):
pass # El método será implementado en las clases derivadas
class Perro(Animal):
def __init__(self, nombre, edad, raza):
# Llamamos al constructor de la clase base (Animal)
super().__init__(nombre, edad)
self.raza = raza
def hacer_sonido(self):
return "Woof!"
Dado que una clase hija hereda los atributos y métodos de la clase padre, esto nos puede ser
muy útil cuando tengamos clases que se parecen entre sí, pero tienen ciertas particularidades. En
este caso, en vez de definir un montón de clases para cada animal, podemos tomar los elementos
comunes y crear una clase “Animal” de la que hereden el resto, respetando, por tanto, la filosofía
DRY (don't repeat yourself). Realizar estas abstracciones y buscar el denominador común para
definir una clase de la que hereden las demás, es una tarea de lo más compleja en el mundo de
la programación.
La clase vieja se llama clase base y la que se construye a partir de ella es una clase derivada. Por
ejemplo, a partir de la clase “Persona”, podemos crear la clase “Empleado” que hereda de
“Persona” y le agregamos el atributo sueldo.
def __init__(self):
self.nombre=input("Ingrese el nombre:")
self.edad=int(input("Ingrese la edad:"))
def imprimir(self):
print("Nombre:",self.nombre)
print("Edad:",self.edad)
class Empleado(Persona):
def __init__(self):
super().__init__()
self.sueldo=float(input("Ingrese el sueldo:"))
def imprimir(self):
super().imprimir()
print("Sueldo:",self.sueldo)
def paga_impuestos(self):
if self.sueldo>3000:
print("El empleado debe pagar impuestos")
else:
print("No paga impuestos")
Librerías en Python
Python cuenta con una amplia variedad de bibliotecas (librerías) que abarcan diversos dominios.
Aquí te presento algunas de las principales y más utilizadas en distintos campos.
Referencias
[Imagen sin título sobre número binario]. (s. f.). https://encrypted-tbn1.gstatic.com/images?
q=tbn:ANd9GcS6rf_STGy_X84p94BQgwuD8QQ1zyRO2xzy2Qc7Uu_gA4yF-UbO