Operaciones con Archivos
Definición de Archivo
Un archivo es un mecanismo que el sistema operativo proporciona para gestionar el almacenamiento en disco. Representa una región designada en el disco duro cuyos datos internos son válidos. Todos los datos en el disco se almacenan en formato binario (1s y 0s). Para relacionar estos datos binarios con formatos de texto, video u otros, se requiere un programa de software que realice la conversión.
En Python, un archivo puede considerarse un tipo de dato, similar a cadenas o listas, sobre el cual se pueden utilizar funciones integradas.
Métodos para Abrir un Archivo
Método 1: Usando la función open
handle = open('ruta/archivo.txt', 'modo', encoding='utf-8') # Abrir archivo de texto
# Realizar operaciones en el archivo
handle.close()
La función open asigna un objeto de archivo a la variable handle. Este proceso determina la ubicación del archivo y cómo cargar los datos del disco a la memoria, pero aún no los carga. Después de abrir el archivo, se pueden realizar varias operaciones. handle.close() es una función integrada del objeto archivo que libera todos los recursos de memoria utilizados durante la apertura y asegura que cualquier dato en el búfer de memoria se escriba en el disco.
Método 2: Usando la sentencia with
Este enfoque utiliza el administrador de contexto para prevenir que olvidemos llamar a close.
with open('ruta/archivo.txt', 'modo', encoding='utf-8') as file_handle:
# Bloque de código: realizar operaciones en el archivo
La palabra clave as actúa como un operador de asignación, asignando el objeto de archivo a file_handle. Cuando el bloque de código dentro de with termina, el sistema ejecuta automáticamente close, liberando la memoria y garantizando la escritura de los datos.
Modos de Apertura de Archivos
Modos de Lectura/Escritura
Modo 'r' (Solo lectura): El archivo solo puede realizar operaciones de lectura.
with open('datos.txt', 'r', encoding='utf-8') as f:
content = f.read() # Lee todos los datos del archivo
Si la ruta del archivo no existe al abrir en modo 'r', se produce un error. Si existe, se lee según la ruta y codificación especificadas.
Modo 'w' (Solo escritura): El archivo solo puede realizar operaciones de escritura.
with open('registro.txt', 'w', encoding='utf-8') as f:
f.write('Texto nuevo') # Escribe contenido en la memoria/búfer
Si la ruta no existe, se crea un archivo nuevo. Si existe, su contenido anterior se sobrescribe (incluso si no se escribe nada, el archivo se trunca al abrirlo en modo 'w').
Modo 'a' (Añadir): Realiza operaciones de escritura, pero sin sobrescribir el contenido existente. El cursor se posiciona al final del archivo.
with open('log.txt', 'a', encoding='utf-8') as f:
f.write('\nNueva entrada')
Modos de Formato de Datos
Modo 't' (Texto): Es el modo predeterminado. La forma completa es 'rt', pero la 't' se omite por defecto. Solo puede manejar archivos de texto.
Modo 'b' (Binario): Puede manejar cualquier tipo de archivo, accediendo directamente a los datos binarios del disco. Se combina con los modos de lectura/escritura ('rb', 'wb', 'ab'). En modo binario, no existe el concepto de codificación, por lo que el parámetro encoding no debe usarse.
Funciones Integradas de Objetos Archivo (Suplemento)
f.read(): Lee todo el contenido del archivo de una vez en la memoria.
Lectura con Bucle for
Para evitar cargar archivos grandes de una sola vez en la memoria:
with open('big_data.csv', 'r', encoding='utf-8') as data_file:
for single_line in data_file:
process(single_line.strip()) # Procesa línea por línea
readline(): Lee una sola línea. readlines(): Lee todas las líneas y las devuelve como una lista.
f.flush(): Vacía el búfer interno del archivo, forzando la escritura de los datos pendientes en el disco (equivalente a Ctrl+S).
f.seek(offset) y f.tell(): Mueven el cursor del archivo a una posición específica o devuelven la posición actual del cursor.
Funciones
Estructura Básica
Definición
def calcular_area(base, altura):
area = base * altura / 2
return area
Llamada
resultado = calcular_area(10, 5)
Valores de Retorno
Valor por defecto: Si una función no tiene sentencia return, su valor de retorno es None.
Uso de return:
returnsolo: Finaliza la función inmediatamente, devuelveNone.return valor: Finaliza la función y devuelve el valor especificado.return v1, v2, ...: Finaliza la función y devuelve los valores como una tupla.
Parámetros de Función
Parámetros Formales
Parámetros por defecto:
def conectar(servidor, puerto=3306):
print(f"Conectando a {servidor}:{puerto}")
conectar("db.principal") # puerto será 3306
Parámetros de longitud variable (*args, **kwargs): Permiten que la función acepte un número variable de argumentos.
def registrar_evento(evento, *detalles, **metadatos):
print(f"Evento: {evento}")
print(f"Detalles: {detalles}")
print(f"Metadatos: {metadatos}")
registrar_evento("inicio_sesion", "usuario1", "web", tiempo=1630000000, exito=True)
Parámetros de palabra clave con nombre (keyword-only): Vienen después de un *args y solo pueden pasarse por nombre.
Argumentos Reales
Por posición: Se asignan a los formales en el orden en que se definen.
Por palabra clave: Asignan valores usando el nombre del parámetro formal, independientemente del orden.
Desempaquetado (* y **):
params = (1, 2, 3)
dic_params = {'x': 10, 'y': 20}
mi_funcion(*params) # Equivalente a mi_funcion(1, 2, 3)
mi_funcion(**dic_params) # Equivalente a mi_funcion(x=10, y=20)
Espacios de Nombres y Alcance
Espacios de Nombres Principales
Integrado (built-in): Contiene todas las funciones integradas (print, len, etc.). Existe mienrtas el intérprete de Python está activo.
Global (módulo): Asociado a un archivo o módulo .py. Se crea al ejecutar el módulo y almacena todas las definiciones de nivel superior.
Local (función): Se crea cuando se llama a una función y almacena las variables definidas dentro de ella.
Orden de Búsqueda
Para encontrar un nombre: Local -> Enclosing (si aplica) -> Global -> Integrado.
Palabras Clave global y nonlocal
global: Permite que una función moidfique una variable en el espacio de nombres global.
nonlocal: Permite que una función anidada modifique una variable en el alcance de la función que la encierra.
Funciones de Cierrre y Decoradores
Funciones de Cierre (Closures)
Ocurre cuando una función anidada recuerda y tiene acceso a las variables de su alcance léxico (la función que la encierra), incluso después de que la función exterior haya terminado de ejecutarse.
def crear_contador(inicio=0):
cuenta = inicio
def incrementar():
nonlocal cuenta
cuenta += 1
return cuenta
return incrementar
mi_contador = crear_contador(10)
print(mi_contador()) # 11
print(mi_contador()) # 12
Decoradores
Un decorador es una función que toma otra función como argumento, extiende su comportamiento y devuelve la función modificada. Permite añadir funcionalidad sin modificar el código fuente original.
Decorador Simple
def logger(func):
def wrapper(*args, **kwargs):
print(f"Ejecutando {func.__name__}")
resultado = func(*args, **kwargs)
print(f"{func.__name__} completada")
return resultado
return wrapper
@logger
def sumar(a, b):
return a + b
Decoradores con Argumentos
def repetir(n):
def decorador(func):
def wrapper(*args, **kwargs):
for _ in range(n):
resultado = func(*args, **kwargs)
return resultado
return wrapper
return decorador
@repetir(3)
def saludar(nombre):
print(f"Hola, {nombre}")
Funciones Recursivas
Una función que se llama a sí misma directa o indirectamente. Requiere un caso base para detener la recursión y evitar un bucle infinito y desbordamiento de pila.
def factorial(n):
if n == 1: # Caso base
return 1
else:
return n * factorial(n - 1) # Paso recursivo
Algoritmos y Búsqueda Binaria
La búsqueda binaria es un algoritmo eficiente para encontrar un elemento en una lista ordenada. Funciona dividiendo repetidamente el intervalo de búsqueda a la mitad.
def busqueda_binaria_iterativa(objetivo, lista_ordenada):
inicio, fin = 0, len(lista_ordenada) - 1
while inicio <= fin:
medio = (inicio + fin) // 2
if lista_ordenada[medio] == objetivo:
return medio
elif lista_ordenada[medio] < objetivo:
inicio = medio + 1
else:
fin = medio - 1
return -1 # No encontrado
def busqueda_binaria_recursiva(objetivo, lista, inicio, fin):
if inicio > fin:
return -1
medio = (inicio + fin) // 2
if lista[medio] == objetivo:
return medio
elif lista[medio] < objetivo:
return busqueda_binaria_recursiva(objetivo, lista, medio + 1, fin)
else:
return busqueda_binaria_recursiva(objetivo, lista, inicio, medio - 1)
Expresiones y Generadores
Expresión Ternaria
resultado = "positivo" if numero > 0 else "no positivo"
Comprensiones de Listas
cuadrados = [x**2 for x in range(10)]
pares = [y for y in range(20) if y % 2 == 0]
Comprensiones de Diccionarios y Conjuntos
# Diccionario
pares_clave_valor = {str(i): i for i in range(5)}
# Conjunto (elimina duplicados)
caracteres_unicos = {c for c in 'programacion'}
Funciones Lambda y Funciones Integradas Clave
Funciones Lambda
doblar = lambda a: a * 2
print(doblar(5)) # 10
Funciones Integradas Importantes
map(función, iterable): Aplica una función a cada elemento de un iterable.filter(función, iterable): Filtra elementos, devolviendo aquellos para los que la función devuelve True.sorted(iterable, key=función): Devuelve una lista ordenada.keyespecifica una función de personalización.reduce(función, iterable): (De functools) Aplica una función acumulativa a los elementos.zip(*iterables): Combina elementos de múltiples iterables en tuplas.
Objetos Iterables e Iteradores
Un iterable (ej: lista, cadena) es un objeto que puede devolver un iterador (tiene el método __iter__). Un iterador es un objeto que representa un flujo de datos (tiene los métodos __iter__ y __next__). El bucle for internamente llama a __iter__ en el iterable y luego repite __next__ hasta que se lanza StopIteration.
Manejo de Excepciones
Las excepciones (errores) se manejan con bloques try...except.
try:
resultado = 10 / 0
except ZeroDivisionError:
print("Error: División por cero.")
except (TypeError, ValueError) as e:
print(f"Error de tipo o valor: {e}")
else:
print("Sin errores.")
finally:
print("Siempre se ejecuta (limpieza).")