Para entender mejor la Programación Orientada a Objetos (POO), es esencial recordar los conceptos básicos de atributos y métodos.
Atributos: Son variables que pertenecen a una clase o a sus objetos. Definen las propiedades de un objeto. Por ejemplo, pensemos en una persona: ¿Qué caracteriza a una persona en general? Las personas tienen nombre, edad, dirección, etc. En términos de POO, estos serían los atributos de la clase Person.
Métodos: Son funciones definidas dentro de una clase que operan sobre sus objetos. Definen los comportamientos de un objeto. Siguiendo con el ejemplo de una persona, ¿Qué acciones puede realizar una persona? Puede hablar, caminar, comer, etc. En POO, estas acciones serían métodos de la clase Person.
Ejemplo Básico de una Clase
classPerson:def__init__(self, name, age): self.name = name # Atributo self.age = age # Atributodefgreet(self):print(f"Hola, mi nombre es {self.name} y tengo {self.age} años.")# Método# Crear una instancia de la clase Personpersona1 = Person("Ana",30)persona1.greet()# Output: Hola, mi nombre es Ana y tengo 30 años.
al usar herencia vimos el método init() que es le cosntructor, el mismo es llamado automáticamente cuando se crea una nueva instancia de una clase y se utiliza para inicializar los atributos del objeto.
Ejemplo de Constructor
classPerson:def__init__(self, name, age): self.name = name
self.age = age
# Crear una instancia de Personperson1 = Person("Ana",30)print(person1.name)# Output: Anaprint(person1.age)# Output: 30
En este ejemplo, el constructor __init__ inicializa los atributos name y age de la clase Person.
Uso de super() en Python
La función super() en Python te permite acceder y llamar a métodos definidos en la superclase desde una subclase. Esto es útil cuando quieres extender o modificar la funcionalidad de los métodos de la superclase sin tener que repetir su implementación completa.
Ejemplo de Uso de super()
classPerson:def__init__(self, name, age): self.name = name
self.age = age
defgreet(self):print("Hello! I am a person.")classStudent(Person):def__init__(self, name, age, student_id):super().__init__(name, age) self.student_id = student_id
defgreet(self):super().greet()print(f"Hi, I'm {self.name}, and I'm a student with ID: {self.student_id}")# Crear instancia de Student y llamar a greetstudent = Student("Ana",20,"S12345")student.greet()# Output: Hello! I am a person.# Hi, I'm Ana, and I'm a student with ID: S12345
En este ejemplo:
La clase Person define un método greet() que imprime un saludo genérico.
La clase Student, que es una subclase de Person, utiliza super().__init__(name, age) para llamar al constructor de la superclase Person y luego sobrescribe el método greet() para agregar información específica del estudiante.
Jerarquía de Clases y Constructores
¿Qué sucede si una clase tiene una clase padre y esa clase padre tiene otra clase padre? En este caso, usamos super() para asegurar que todas las clases padre sean inicializadas correctamente.
Ejemplo de Jerarquía de Clases
classLivingBeing:def__init__(self, name): self.name = name
classPerson(LivingBeing):def__init__(self, name, age):super().__init__(name) self.age = age
classStudent(Person):def__init__(self, name, age, student_id):super().__init__(name, age) self.student_id = student_id
defintroduce(self):print(f"Hi, I'm {self.name}, {self.age} years old, and my student ID is {self.student_id}")# Crear instancia de Studentstudent = Student("Carlos",21,"S54321")student.introduce()# Output: Hi, I'm Carlos, 21 years old, and my student ID is S54321
En este ejemplo:
LivingBeing es la clase base que inicializa el atributo name.
Person es una subclase de LivingBeing que inicializa name a través de super().__init__(name) y luego inicializa age.
Student es una subclase de Person que inicializa name y age a través de super().__init__(name, age) y luego inicializa student_id.
Métodos que Vienen por Defecto en Python
En Python, todas las clases heredan de la clase base object. Esto significa que todas las clases tienen ciertos métodos por defecto, algunos de los cuales pueden ser útiles para personalizar el comportamiento de tus clases.
Métodos por Defecto Más Comunes
__init__(self): Constructor de la clase. Es llamado cuando se crea una nueva instancia de la clase. Inicializa los atributos del objeto.
__str__(self): Devuelve una representación en cadena del objeto, utilizada por print() y str(). Este método es útil para proporcionar una representación legible del objeto.
__repr__(self): Devuelve una representación "oficial" del objeto, utilizada por repr(). Este método está diseñado para devolver una cadena que represente al objeto de manera que se pueda recrear.
Ejemplo de Métodos __str__ y __repr__
Vamos a crear una clase Person que sobrescriba los métodos __str__ y __repr__.
classPerson:def__init__(self, name, age): self.name = name
self.age = age
def__str__(self):returnf"{self.name}, {self.age} años"def__repr__(self):returnf"Person(name={self.name}, age={self.age})"# Crear instancias de Personperson1 = Person("Alice",30)person2 = Person("Bob",25)# Uso de __str__print(person1)# Output: Alice, 30 años# Uso de __repr__print(repr(person1))# Output: Person(name=Alice, age=30)
Explicación del Código
El método __str__ devuelve una representación en cadena del objeto, útil para mensajes de salida amigables.
El método __repr__ devuelve una representación más detallada del objeto, útil para la depuración.
Estos métodos proporcionan una manera conveniente de representar y comparar objetos, lo que facilita la depuración y el uso de los objetos en el código.
Importancia de Aprender estos Conceptos
Comprender y utilizar super(), los métodos por defecto y los constructores es crucial para escribir código limpio, eficiente y reutilizable en Python. Estos conceptos permiten:
Extender Funcionalidades: super() permite extender las funcionalidades de una superclase sin duplicar código.
Inicialización Correcta: El uso adecuado de constructores asegura que todos los atributos sean inicializados correctamente.
Personalizar Representaciones: Métodos como __str__ y __repr__ permiten personalizar cómo se representan los objetos, facilitando la depuración y el manejo de datos.
Comparar y Ordenar Objetos: Métodos como __eq__, __lt__, etc., permiten definir cómo se comparan y ordenan los objetos, lo cual es esencial para muchas operaciones de datos.
Entendí mucho mejor la POO pero es verdad que para nosotros los novatos en estos temas estaría genial un video de introducción para que no nos perdamos tanto y evitemos la frustración al inicio de no entender nada.
Paso a paso todo se consigue :D
si, el primer video me confundí mucho pero ya al segundo entendí que era un tema largo y de practica, ahora en esta clase ya entiendo mas como funciona y me emociona aplicarlo, así como se ve, puede ser muy útil en la vida cotidiana, tal vez como todo lo que ya hemos visto se trata de profundizar, pero concuerdo con que debieron habérnoslo advertido, tal vez para Carli ya es un tema fácil y por eso no nos lo advirtió jaja
Resumen y Explicación
Atributos y Métodos
Atributos: Son variables asociadas a una clase o a sus objetos que definen sus propiedades. Por ejemplo, una clase Persona podría tener atributos como nombre, edad y dirección.
Métodos: Son funciones definidas dentro de una clase que describen los comportamientos de los objetos de esa clase. Por ejemplo, en la clase Persona, podríamos tener métodos como hablar, caminar y comer.
Uso de super() en Python
La función super() permite acceder y llamar a métodos definidos en una superclase desde una subclase. Esto es útil para extender o modificar la funcionalidad de los métodos de la superclase sin repetir la implementación completa.
Jerarquía de Clases y Constructores
Cuando una clase hereda de otra, y esta a su vez hereda de otra clase, super() se utiliza para asegurar que todas las clases padre sean inicializadas correctamente.
Métodos que Vienen por Defecto en Python
Todas las clases en Python heredan de la clase base object, lo que proporciona ciertos métodos por defecto:
__init__(self): Constructor de la clase, se llama al crear una nueva instancia y se utiliza para inicializar atributos.
__str__(self): Devuelve una representación en cadena del objeto, usada por print() y str().
__repr__(self): Devuelve una representación “oficial” del objeto, usada por repr() y diseñada para ser precisa y útil para recrear el objeto.
Importancia de Aprender estos Conceptos
Extender Funcionalidades: super() permite extender funcionalidades de la superclase sin duplicar código.
Inicialización Correcta: El uso adecuado de constructores garantiza que todos los atributos sean inicializados correctamente.
Personalizar Representaciones: Métodos como __str__ y __repr__ permiten personalizar la representación de los objetos, facilitando la depuración y manejo de datos.
Comparar y Ordenar Objetos: Métodos como __eq__, __lt__, etc., permiten definir cómo se comparan y ordenan los objetos, esencial para muchas operaciones de datos.
Excelente!
Estoy muy atorado con esto, pude hacer los ejercicios, pero me cuesta mucho entenderlo y poder aplicarlo en otros casos más complejos.
Rey, te entiendo, yo tuve que repetir muchas veces los cursos para poder entenderlo mejor, aun me cuesta, pero poco a poco, el objetivo es repetir y practicar.
Rey, es normal. Hay cosas que cuesta más que otras cuando se trata de aprenderlas. Yo he estado igual con este concepto.
trata de practicar mucho y re ver las clases de ser necesario, así como otros recursos en internet. En youtube hay mucho material sobre P.O.O.
Esta parte necesita ser corregida, tiene muchas faltas ortograficas, por ejemplo en este parrafo ( al usar herencia vimos el método init() que es le cosntructor, el mismo es llamado automáticamente cuando se crea una nueva instancia de una clase y se utiliza para inicializar los atributos del objeto.)
me sorprendio lo de los metodos
__str__ y __repr__ eso faciliita mucho las cosas
Recursos que abren posibilidades!
La Programación Orientada a Objetos (POO) en Python es un paradigma de programación que organiza el código en clases y objetos. Este enfoque permite modelar el mundo real más fácilmente y escribir programas más modulares, reutilizables y escalables.
Las clases son plantillas que permiten crear objetos, que son instancias de esas clases. Las clases pueden tener atributos (variables) y métodos (funciones.
Conceptos clave:
Atributos: Variables que describen las características de un objeto (ej: nombre, edad).
Métodos: Funciones que definen el comportamiento de un objeto (ej: hablar, caminar).
Constructor (__init__): Método especial llamado automáticamente al crear un objeto. Inicializa los atributos del objeto.
Herencia ysuper(): Permite que una clase (subclase) herede atributos y métodos de otra clase (superclase). super() se usa para llamar al constructor o métodos de la superclase desde la subclase, evitando la repetición de código. Es fundamental para construir jerarquías de clases donde las subclases añaden o modifican el comportamiento de las superclases.
Métodos por defecto: Python provee métodos predefinidos como __str__ (representación en cadena para print()) y __repr__ (representación "oficial" para depuración), que se pueden personalizar para controlar cómo se muestran los objetos.
En resumen:
La POO permite crear "objetos" que combinan datos (atributos) y funciones que operan sobre esos datos (métodos). La herencia facilita la creación de nuevas clases basadas en clases existentes, reutilizando código y extendiendo funcionalidades.
Los constructores aseguran que los objetos se inicialicen correctamente, y los métodos especiales permiten personalizar la interacción con los objetos.
Dominar estos conceptos es esencial para escribir código Python limpio, eficiente y reutilizable.
No me quedó muy claro la utilidad del __str__ y el __repr__
Lo veo como que pudieran asignar cualquier otro nombre a la funcion y dar parametros similares a los que mostraron para dichos metodos.
Al fin y al cabo se tienen que escribir manualmente.
A menos que sean buenas practicas, es diferente.
Pero no les veo esa utilidad extra a los metodos.
Tal vez me estoy perdiendo de algo.
estoy con el caballero, ademas que no se nota la diferencia parecen lo mismo, como dijo hay que escribir manualmente
En la lectura se da por entendido que se usa de manera mas explicita y personalizada la salida del en el código.
El método __str__ devuelve una representación en cadena del objeto, útil para mensajes de salida amigables.
El método __repr__ devuelve una representación más detallada del objeto, útil para la depuración.
Señores buen dia! Espero esta implementación de un ejemplo de POO con animales les pueda orientar, investigando un poco e interactuando con el codigo pude, hacer una clase bastante buena y aplicando los 4 pilares de la POO, espero les pueda orientar:
from abc importABC, abstractmethod
import os
os.system('cls')# Clase abstracta
classAnimal(ABC): # Implementación de Type hints
def __init__(self,raza:str,onomatopeya:str): self._raza= raza
self._onomatopeya= onomatopeya # Descripción del sonido con el que se comunica el animal
@property
def razaAnimal(self)->str:return self._raza @razaAnimal.setter def razaAnimal(self, nuevaRaza):ifisinstance(nuevaRaza, str): self._raza= nuevaRaza
else: raise ValueError("La raza debe ser un string")
@property
def onomatopeyaAnimal(self)->str:return self._onomatopeya def valorCuidoxKilo(self,valor: int,kilo: int): raise NotImplementedError("Esta clase solo debe ser implementada por una subclase")
@abstractmethod
def habilidad(self): pass
@onomatopeyaAnimal.setter def onomatopeyaAnimal(self, nuevaOnomatopeya):ifisinstance(nuevaOnomatopeya, str): self._onomatopeya= nuevaOnomatopeya
else: raise ValueError("La onomatopeya debe ser un string") def __str__(self)->str:return f"El {self.razaAnimal} y dice {self.onomatopeyaAnimal}"classComportamiento(Animal): def __init__(self,raza: str,onomatopeya: str,defensa: str):super().__init__(raza, onomatopeya) self._defensa= defensa
@property
def defensa(self)->str:return self._defensa @defensa.setter def defensa(self, nuevoDefensa):ifisinstance(nuevoDefensa, str): self._defensa= nuevoDefensa
else: raise ValueError("La defensa debe ser un string") def metodoDefensa(self):return f"\nEl {self.razaAnimal} y su metodo de defensa, primero te dice {self.onomatopeyaAnimal} y despues {self.defensa}" # Uso de Abstracción def habilidad(self):return f"\nEl {self.razaAnimal} puede olfatear para detectar por Ejemplo: Narcoticos, Explosivos" # Uso de polimorfismo
def valorCuidoxKilo(self,valor:int,kilo:int):return f"\nEl perro come {kilo}Kg de purina, y su valor es: ${valor * kilo} pesos colombianos"# SubclasePerro que hereda de animal
classPerro(Animal): # Uso de Abstracción def habilidad(self):return"\nEl perro puede olfatear para detectar por Ejemplo: Narcoticos, Explosivos" # Uso de polimorfismo
def valorCuidoxKilo(self,valor:int,kilo:int):return f"\nEl perro come {kilo}Kg de purina, y su valor es: ${valor * kilo} pesos colombianos"# SubclaseGato que hereda de animal
classGato(Animal): def habilidad(self):return"\nEl gato puede escalar arboles" # Uso de polimorfismo
def valorCuidoxKilo(self,valor:int,kilo:int):return f"\nEl gato come {kilo}Kg de catChow, y su valor es: ${valor * kilo} pesos colombianos"# INSTANCIASDECLASEScomportamiento =Comportamiento("perro","guau","te muerde")print(comportamiento)print(comportamiento.habilidad())print(comportamiento.valorCuidoxKilo(7000,2))print("\n===========================================")perro =Perro("perro","guaua")print(perro.habilidad())print(perro.valorCuidoxKilo(8000,3))print("\n===========================================")gato =Gato("gato","miau")print(gato.habilidad())print(gato.valorCuidoxKilo(5000,5))```from abc importABC, abstractmethodimport os
os.system('cls')\# Clase abstractaclass Animal(ABC): # Implementación de Type hints def \_\_init\_\_(self,raza:str,onomatopeya:str): self.\_raza = raza self.\_onomatopeya = onomatopeya # Descripción del sonido con el que se comunica el animal
@property def razaAnimal(self)->str:return self.\_raza @razaAnimal.setter def razaAnimal(self, nuevaRaza):ifisinstance(nuevaRaza, str): self.\_raza = nuevaRaza else: raise ValueError("La raza debe ser un string") @property def onomatopeyaAnimal(self)->str:return self.\_onomatopeya def valorCuidoxKilo(self,valor: int,kilo: int): raise NotImplementedError("Esta clase solo debe ser implementada por una subclase") @abstractmethod def habilidad(self): pass @onomatopeyaAnimal.setter def onomatopeyaAnimal(self, nuevaOnomatopeya):ifisinstance(nuevaOnomatopeya, str): self.\_onomatopeya = nuevaOnomatopeya else: raise ValueError("La onomatopeya debe ser un string") def \_\_str\_\_(self)->str:return f"El {self.razaAnimal} y dice {self.onomatopeyaAnimal}" classComportamiento(Animal): def \_\_init\_\_(self,raza: str,onomatopeya: str,defensa: str):super().\_\_init\_\_(raza, onomatopeya) self.\_defensa = defensa
@property def defensa(self)->str:return self.\_defensa @defensa.setter def defensa(self, nuevoDefensa):ifisinstance(nuevoDefensa, str): self.\_defensa = nuevoDefensa else: raise ValueError("La defensa debe ser un string") def metodoDefensa(self):return f"\nEl {self.razaAnimal} y su metodo de defensa, primero te dice {self.onomatopeyaAnimal} y despues {self.defensa}" # Uso de Abstracción def habilidad(self):return f"\nEl {self.razaAnimal} puede olfatear para detectar por Ejemplo: Narcoticos, Explosivos" # Uso de polimorfismo def valorCuidoxKilo(self,valor:int,kilo:int):return f"\nEl perro come {kilo}Kg de purina, y su valor es: ${valor \* kilo} pesos colombianos"\# SubclasePerro que hereda de animalclass Perro(Animal): # Uso de Abstracción def habilidad(self):return"\nEl perro puede olfatear para detectar por Ejemplo: Narcoticos, Explosivos" # Uso de polimorfismo def valorCuidoxKilo(self,valor:int,kilo:int):return f"\nEl perro come {kilo}Kg de purina, y su valor es: ${valor \* kilo} pesos colombianos"\# SubclaseGato que hereda de animalclass Gato(Animal): def habilidad(self):return"\nEl gato puede escalar arboles" # Uso de polimorfismo def valorCuidoxKilo(self,valor:int,kilo:int):return f"\nEl gato come {kilo}Kg de catChow, y su valor es: ${valor \* kilo} pesos colombianos"\# INSTANCIASDECLASEScomportamiento =Comportamiento("perro","guau","te muerde")print(comportamiento)print(comportamiento.habilidad())print(comportamiento.valorCuidoxKilo(7000,2))print("\n===========================================")perro =Perro("perro","guaua")print(perro.habilidad())print(perro.valorCuidoxKilo(8000,3))print("\n===========================================")gato =Gato("gato","miau")print(gato.habilidad())print(gato.valorCuidoxKilo(5000,5))
porque despues de def greet(self): se escribe super().greet() osea greet se llama a si mismo o porque poner greet otra vez?
Se utiliza super().greet() dentro de def greet(self): para llamar al método greet() de la superclase en una subclase, permitiendo extender o modificar su comportamiento.
Veo que este curso está un poco loco. Esta clase no aparece en el indice de clases.
:O, ahora veo qué pasa, gracias por la observación
Muchas gracias por tan buena explicación , los ejercicios todo estuvo muy entendible . Súper. Ahora vamos a la práctica.
éxito :D
class Persona:
def __init__(self, nombre, edad):
self.nombre = nombre
self.edad = edad
print("Constructor de Persona llamado")
class Estudiante(Persona):
def __init__(self, nombre, edad, carrera):
# Usamos super() para inicializar los atributos de la clase Persona
super().__init__(nombre, edad)
# Inicializamos el atributo específico de Estudiante
alumno = Estudiante("Karla", 20, "Ingeniería en Sistemas")
alumno.mostrar_informacion()
Cuáles son los 4 pilares de la POO?
Pilar clave
Encapsulación
Proteger datos
Abstracción
Mostrar lo importante
Herencia
Reutilizar código
Polimorfismo
Mismo método, distintos comportamientos
Excelente curso! ¿Cuando personalizamos representaciones con __srt__ o __repr__ estamos aplicando polimorfismo?
Tambien seria interesante que para futuros cursos de python avanzados abordarante temas como:
* Context Manager Types
* Type Annotation Types
* Abstract Base Classes
* Data Classes
- En cuanto al Encapsulamiento, el acceso a los atributos publico, protegidos y privados.
- El uso de __dict__ en las clases, entre otros.
Eso es verdad la parte de acceso a clases públicas y privadas creo que faltaría pero no se si lo manejas en Python en Java se que lo haces.
Hola, recomiendo buscar videos y otras lecturas sobre POO. A veces entendemos mejor con otros autores y entre todas las fuentes sacamos mejor provecho. Para mí que ya traigo bases, Carli me pareció muy buena.
Considero que el tema de Programación Orientada a Objetos (POO) puede ser un poco complejo al principio. Sin embargo, a mí me ayudó muchísimo complementar el contenido con otro curso enfocado exclusivamente en POO, el cual me dejó mucho más claros los conceptos. Les comparto el enlace por si a alguien más le sirve:
creo que para entenderlo mejor es util apollarse con un caso de la vida real, es decir aplicable.
Los métodos __eq__ y __lt__ son métodos mágicos en Python que permiten definir el comportamiento de comparación de los objetos de una clase.
__eq__(self, other): Este método se utiliza para comparar si dos objetos son iguales. Si se implementa, permite usar el operador == para comparar instancias de la clase.
__lt__(self, other): Este método permite definir el comportamiento del operador < (menor que). Si se implementa, se puede utilizar para determinar si una instancia de la clase es menor que otra.
Implementar estos métodos permite personalizar la forma en que se comparan los objetos en tu clase, facilitando su uso en estructuras de datos que dependen de comparación (como listas ordenadas).