Python para Principiantes
Cheatsheet Content
### Programación Orientada a Objetos (POO) - **Explicación sencilla:** Es una forma de organizar tu código usando "clases" (planos) para crear "objetos" (cosas que existen en tu programa). Imagina que quieres hacer galletas: la **receta** es la clase, y cada **galleta** que haces es un objeto. #### Clases - **Explicación sencilla:** La "receta" o el "plano" que describe cómo serán tus objetos. Define qué datos (atributos) tendrán y qué pueden hacer (métodos). - **Sintaxis básica:** ```python class NombreDeMiClase: # Aquí van los atributos de clase y los métodos ``` - **Ejemplo corto:** ```python class Fruta: # Definimos la clase "Fruta" pass # 'pass' significa no hacer nada, solo para que no esté vacía ``` - **Errores comunes:** - **Olvidar `class`:** Intentar definir una clase sin la palabra clave. - **Nombre de clase:** Por convención, las clases empiezan con mayúscula (`MiClase`). - **Cuándo usarlo:** Cuando quieres definir un tipo de "cosa" en tu programa que tendrá características y comportamientos similares (ej. `Usuario`, `Producto`, `Sensor`). #### Objetos - **Explicación sencilla:** Son las "cosas" que creas a partir de una clase. Cada objeto es una instancia individual de la clase. Volviendo al ejemplo de las galletas, cada galleta individual es un objeto de la clase `RecetaDeGalleta`. - **Sintaxis básica:** ```python mi_objeto = NombreDeMiClase(valor1, valor2) # Creamos un objeto, se llama "instanciar" ``` - **Ejemplo corto:** ```python class Fruta: pass manzana = Fruta() # Creamos un objeto 'manzana' de la clase Fruta banana = Fruta() # Creamos otro objeto 'banana' de la clase Fruta ``` - **Errores comunes:** - **Olvidar `()`:** `objeto = MiClase` (sin paréntesis) no crea un objeto, sino que refiere a la clase misma. - **No pasar argumentos:** Si el constructor (`__init__`) de la clase pide argumentos, debes pasarlos al crear el objeto. - **Cuándo usarlo:** Cada vez que necesitas una "cosa" concreta en tu programa que tenga las propiedades y habilidades definidas por una clase. #### Constructor `__init__` - **Explicación sencilla:** Es un método especial que se ejecuta automáticamente cada vez que creas un nuevo objeto de una clase. Su trabajo principal es darle a ese nuevo objeto sus valores iniciales (sus atributos). - **Sintaxis básica:** ```python class MiClase: def __init__(self, parametro1, parametro2): self.atributo1 = parametro1 # Guarda el parametro1 en el atributo 'atributo1' del objeto self.atributo2 = parametro2 # 'self' se refiere al objeto que se está construyendo ``` - **Ejemplo corto:** ```python class Animal: def __init__(self, nombre, especie): # 'self.nombre' y 'self.especie' son atributos del objeto que se crea self.nombre = nombre self.especie = especie self.hambriento = True # Atributo inicial por defecto perro = Animal("Firulais", "Perro") # Al hacer esto se llama a __init__ gato = Animal("Mishu", "Gato") print(perro.nombre) # Imprime: Firulais print(gato.especie) # Imprime: Gato print(perro.hambriento) # Imprime: True ``` - **Errores comunes:** - **Olvidar `self`:** `self` debe ser siempre el primer parámetro de `__init__` (y de cualquier método de instancia). - **No inicializar atributos:** No crear `self.atributo = parametro` hace que el objeto no tenga ese atributo. - **Cuándo usarlo:** Siempre que tus objetos necesiten tener valores iniciales o configuraciones al ser creados. #### Atributos - **Explicación sencilla:** Son las características o propiedades que describen a un objeto (ej. el color de un coche, la edad de una persona). Se guardan dentro del objeto. - **Sintaxis básica:** ```python # Dentro del constructor o método: self.nombre_atributo = valor # Fuera del objeto (para acceder): objeto.nombre_atributo ``` - **Ejemplo corto:** ```python class Libro: def __init__(self, titulo, autor): self.titulo = titulo # Atributo 'titulo' del objeto self.autor = autor # Atributo 'autor' del objeto self.leido = False # Atributo con valor por defecto mi_libro = Libro("Cien años de soledad", "Gabo") print(f"Título: {mi_libro.titulo}") # Acceder al atributo my_libro.leido = True # Cambiar el valor de un atributo print(f"¿Leído?: {mi_libro.leido}") ``` - **Errores comunes:** - **Acceder antes de inicializar:** Si un atributo no se define en `__init__`, puede que el objeto no lo tenga. - **Confundir atributos de clase con de instancia:** Un atributo de clase es el mismo para *todos* los objetos. Uno de instancia es *único* para cada objeto. - **Cuándo usarlo:** Para almacenar los datos específicos de cada objeto. #### Métodos - **Explicación sencilla:** Son funciones que pertenecen a una clase y describen las acciones que los objetos de esa clase pueden hacer (ej. un coche puede "arrancar", una persona puede "hablar"). - **Sintaxis básica:** ```python class MiClase: def nombre_metodo(self, arg1, arg2): # Código del método. 'self' es el objeto que llama al método. print(f"Estoy en el objeto: {self}") # ... ``` - **Ejemplo corto:** ```python class Persona: def __init__(self, nombre, edad): self.nombre = nombre self.edad = edad def saludar(self): # Método 'saludar' print(f"Hola, mi nombre es {self.nombre}.") def cumplir_anios(self): # Método 'cumplir_anios' self.edad += 1 print(f"¡Feliz cumpleaños! Ahora tengo {self.edad} años.") p1 = Persona("Carlos", 30) p1.saludar() # Llamar al método: "Hola, mi nombre es Carlos." p1.cumplir_anios() # Llamar al método: "¡Feliz cumpleaños! Ahora tengo 31 años." ``` - **Errores comunes:** - **Olvidar `self`:** Es el primer parámetro obligatorio en cualquier método de instancia. - **Intentar acceder sin un objeto:** No puedes llamar `Persona.saludar()` directamente sin crear un objeto (`p1 = Persona(...)` primero). - **Cuándo usarlo:** Para definir acciones o comportamientos específicos que pertenecen a los objetos de una clase, y que a menudo interactúan con los atributos de ese mismo objeto. #### Encapsulamiento - **Explicación sencilla:** Es la idea de "proteger" los datos internos de un objeto. Hacemos que algunos atributos no sean fácilmente accesibles o modificables desde fuera del objeto, forzando a usar métodos específicos para interactuar con ellos. Es como si un coche tuviera un motor (datos internos) que solo se manipula a través del volante y los pedales (métodos). - **Sintaxis básica:** Python no tiene un encapsulamiento estricto como otros lenguajes. Se usa una convención: - `_nombre_atributo`: Se considera "protegido", no se debe acceder directamente desde fuera. - `__nombre_atributo`: Python lo "modifica" para que sea más difícil accederlo desde fuera (se llama "name mangling"). - **Ejemplo corto:** ```python class CuentaBancaria: def __init__(self, saldo_inicial): self.__saldo = saldo_inicial # Atributo "privado" (doble guion bajo) def depositar(self, cantidad): # Método público para modificar el saldo if cantidad > 0: self.__saldo += cantidad print(f"Depósito de {cantidad}. Nuevo saldo: {self.__saldo}") else: print("La cantidad debe ser positiva.") def ver_saldo(self): # Método público para acceder al saldo return self.__saldo micuenta = CuentaBancaria(100) micuenta.depositar(50) # Uso correcto # print(micuenta.__saldo) # Esto daría un error (en realidad __saldo se transforma en _CuentaBancaria__saldo) print(micuenta.ver_saldo()) # Acceso controlado: 150 ``` - **Errores comunes:** - **Intentar acceder directamente:** Intentar modificar `micuenta.__saldo = 500` desde fuera es mala práctica y puede que no funcione como esperas. - **Olvidar getters/setters:** Si quieres que el usuario pueda ver o cambiar un atributo "interno", debes crear métodos específicos para ello. - **Cuándo usarlo:** - Cuando un atributo debe ser modificado o accedido solo bajo ciertas reglas o a través de métodos de control. - Para mantener la coherencia de los datos del objeto y su lógica interna. #### Herencia - **Explicación sencilla:** Permite que una clase ("clase hija" o "subclase") tome prestadas (herede) todas las características (atributos) y acciones (métodos) de otra clase ("clase padre" o "superclase") y luego añada las suyas propias o modifique las heredadas. Es como un hijo que hereda ciertas características de sus padres. - **Sintaxis básica:** ```python class ClaseHija(ClasePadre): # La ClaseHija hereda de ClasePadre def __init__(self, args_padre, arg_hijo): super().__init__(args_padre) # Llamar al constructor del padre self.atributo_hijo = arg_hijo # Atributo propio de la hija # Métodos propios de la hija o que modifican/extienden los del padre ``` - **Ejemplo corto:** ```python class Vehiculo: # Clase Padre def __init__(self, marca, modelo): self.marca = marca self.modelo = modelo self.velocidad = 0 def acelerar(self, cantidad): self.velocidad += cantidad print(f"Acelerando a {self.velocidad} km/h.") class Coche(Vehiculo): # Clase Hija "Coche" hereda de "Vehiculo" def __init__(self, marca, modelo, puertas): super().__init__(marca, modelo) # Llama al __init__ de Vehiculo self.puertas = puertas # Atributo nuevo del Coche def abrir_puertas(self): # Método nuevo del Coche print(f"El {self.marca} {self.modelo} de {self.puertas} puertas abre las puertas.") mi_coche = Coche("Toyota", "Corolla", 4) mi_coche.acelerar(50) # Método heredado de Vehiculo mi_coche.abrir_puertas() # Método propio de Coche ``` - **Errores comunes:** - **Olvidar `super().__init__(...)`:** Si la clase padre tiene un constructor, la hija debe llamarlo para que los atributos del padre se inicialicen correctamente. - **Modificar métodos sin `super()`:** Si sobrescribes un método pero quieres que la lógica del padre también se ejecute, debes usar `super().nombre_metodo(...)` dentro del método sobrescrito. - **Cuándo usarlo:** - Cuando tienes clases que comparten muchas características y comportamientos, pero tienen algunas diferencias específicas. - Para crear jerarquías de objetos que modelen relaciones del mundo real (ej. `Animal` -> `Perro`, `Gato`). - Para reutilizar código y hacer el diseño más limpio y modular.