Conceptos Fundamentales de Python: Archivos, Funciones y Estructuras Avanzadas

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:

  • return solo: Finaliza la función inmediatamente, devuelve None.
  • 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. key especifica 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).")

Etiquetas: Python operaciones_archivos funciones espacios_nombres decoradores

Publicado el 7-24 10:11