Programación Orientada a Objetos en Python: Guía Completa y Práctica
Python ha sido un lenguaje orientado a objetos desde su creación. Crear y usar clases y objetos es muy sencillo. Este capítulo te ayuda a convertirte en experto en el soporte de POO de Python.
Si no tienes experiencia previa con POO, consulta un curso introductorio para comprender los conceptos básicos.
Visión General de Terminología POO
Clase: Prototipo definido por el usuario para un objeto que define atributos (miembros de datos y métodos) que caracterizan cualquier objeto de la clase.
Variable de clase: Variable compartida por todas las instancias de una clase. Definida dentro de la clase pero fuera de los métodos.
Miembro de datos: Variable de clase o instancia que almacena datos asociados a una clase y sus objetos.
Sobrecarga de funciones: Asignación de más de un comportamiento a una función según los tipos de objetos o argumentos.
Variable de instancia: Variable definida dentro de un método que pertenece solo a la instancia actual.
Herencia: Transferencia de características de una clase a otras derivadas de ella.
Instancia: Objeto individual de una cierta clase.
Instanciación: Creación de una instancia de una clase.
Método: Función especial definida en una clase.
Objeto: Instancia única de una estructura de datos definida por su clase. Incluye miembros de datos y métodos.
Sobrecarga de operadores: Asignación de más de una función a un operador.
Creación de Clases
La sentencia class crea una nueva definición de clase:
class ClassName:
'Optional class documentation string'
class_suite
- La clase tiene una cadena de documentación accesible via ClassName.__doc__.
- class_suite contiene todas las sentencias que definen miembros, atributos y funciones.
Ejemplo
class Employee:
'Common base class for all employees'
empCount = 0
def __init__(self, name, salary):
self.name = name
self.salary = salary
Employee.empCount += 1
def displayCount(self):
print("Total Employee %d" % Employee.empCount)
def displayEmployee(self):
print("Name:", self.name, ", Salary:", self.salary)
- empCount es variable de clase compartida. Accesible como Employee.empCount.
- __init__() es el constructor, llamado al crear nueva instancia.
- Los métodos tienen self como primer argumento (Python lo añade automáticamente).
Creación de Objetos Instancia
Para crear instancias, llama a la clase con los argumentos que acepta __init__:
emp1 = Employee("Zara", 2000)
emp2 = Employee("Manni", 5000)
Acceso a Atributos
Usa el operador punto con el objeto. Variables de clase se acceden con el nombre de la clase:
emp1.displayEmployee()
emp2.displayEmployee()
print("Total Employee %d" % Employee.empCount)
Ejemplo Completo
#!/usr/bin/python
class Employee:
'Common base class for all employees'
empCount = 0
def __init__(self, name, salary):
self.name = name
self.salary = salary
Employee.empCount += 1
def displayCount(self):
print("Total Employee %d" % Employee.empCount)
def displayEmployee(self):
print("Name:", self.name, ", Salary:", self.salary)
emp1 = Employee("Zara", 2000)
emp2 = Employee("Manni", 5000)
emp1.displayEmployee()
emp2.displayEmployee()
print("Total Employee %d" % Employee.empCount)
Resultado:
Name: Zara , Salary: 2000 Name: Manni , Salary: 5000 Total Employee 2
Puedes añadir, eliminar o modificar atributos dinámicamente:
emp1.age = 7 # Añadir emp1.age = 8 # Modificar del emp1.age # Eliminar
Funciones integradas para acceso a atributos:
- getattr(obj, name[, default]): Acceder a atributo.
- hasattr(obj, name): Verificar si existe atributo.
- setattr(obj, name, value): Establecer atributo (crea si no existe).
- delattr(obj, name): Eliminar atributo.
Atributos de Clase Integrados
Cada clase Python mantiene estos atributos integrados:
- __dict__: Diccionario con el espacio de nombres de la clase.
- __doc__: Cadena de documentación de la clase.
- __name__: Nombre de la clase.
- __module__: Nombre del módulo donde se define la clase.
- __bases__: Tupla con las clases base.
Destrucción de Objetos (Recolección de Basura)
Python elimina automáticamente objetos innecesarios para liberar memoria. El recolector de basura se ejecuta durante la ejecución del programa y se activa cuando el contador de referencias de un objeto llega a cero.
El contador aumenta al asignar nuevo nombre o colocar en contenedor (lista, tupla, diccionario). Disminuye al usar del, reasignar referencia o salir de ámbito. Al llegar a cero, Python lo recolecta automáticamente.
Una clase puede implementar __del__() (destructor), invocado cuando la instancia está a punto de ser destruida, útil para limpiar recursos no de memoria.
Ejemplo
#!/usr/bin/python
class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def __del__(self):
class_name = self.__class__.__name__
print(class_name, "destroyed")
pt1 = Point()
pt2 = pt1
pt3 = pt1
print(id(pt1), id(pt2), id(pt3))
del pt1
del pt2
del pt3
Resultado: Point destroyed (una sola vez, cuando la última referencia se elimina).
Herencia de Clases
Puedes crear una clase derivándola de una preexistente listando la clase padre entre paréntesis.
Sintaxis
class SubClassName(ParentClass1[, ParentClass2, ...]):
'Optional class documentation string'
class_suite
Ejemplo
#!/usr/bin/python
class Parent:
parentAttr = 100
def __init__(self):
print("Calling parent constructor")
def parentMethod(self):
print('Calling parent method')
def setAttr(self, attr):
Parent.parentAttr = attr
def getAttr(self):
print("Parent attribute:", Parent.parentAttr)
class Child(Parent):
def __init__(self):
print("Calling child constructor")
def childMethod(self):
print('Calling child method')
c = Child()
c.childMethod()
c.parentMethod()
c.setAttr(200)
c.getAttr()
Resultado:
Calling child constructor Calling child method Calling parent method Parent attribute: 200
También puedes heredar de múltiples clases padre:
class A: ... class B: ... class C(A, B): ...
Funciones para verificar relaciones:
- issubclass(sub, sup): True si sub es subclase de sup.
- isinstance(obj, Class): True si obj es instancia de Class o subclase.
Sobrescritura de Métodos
Puedes sobrescribir métodos de la clase padre para funcionalidad especial en la subclase.
Ejemplo
#!/usr/bin/python
class Parent:
def myMethod(self):
print('Calling parent method')
class Child(Parent):
def myMethod(self):
print('Calling child method')
c = Child()
c.myMethod()
Resultado: Calling child method
Métodos Base de Sobrecarga
| Método | Descripción | Llamada de Ejemplo |
|---|---|---|
| __init__(self[, args...]) | Constructor | obj = ClassName(args) |
| __del__(self) | Destructor | del obj |
| __repr__(self) | Representación string evaluable | repr(obj) |
| __str__(self) | Representación string imprimible | str(obj) |
| __cmp__(self, x) | Comparación de objetos | cmp(obj, x) |
Sobrecarga de Operadores
Define métodos especiales para que los operadores funcionen con tus objetos. Ejemplo con vectores:
#!/usr/bin/python
class Vector:
def __init__(self, a, b):
self.a = a
self.b = b
def __str__(self):
return 'Vector (%d, %d)' % (self.a, self.b)
def __add__(self, other):
return Vector(self.a + other.a, self.b + other.b)
v1 = Vector(2, 10)
v2 = Vector(5, -2)
print(v1 + v2)
Resultado: Vector(7, 8)
Ocultamiento de Datos
Los atributos con doble guion bajo (__secretCount) no son visibles directamente desde fuera de la clase.
Ejemplo
#!/usr/bin/python
class JustCounter:
__secretCount = 0
def count(self):
self.__secretCount += 1
print(self.__secretCount)
counter = JustCounter()
counter.count()
counter.count()
print(counter.__secretCount) # AttributeError
Python cambia internamente el nombre a _ClassName__attrName. Para acceder: counter._JustCounter__secretCount.
python
- Seguimiento Automático de Objetos por Visión Artificial con Raspberry Pi y OpenCV
- Clases y objetos en C#: Fundamentos para POO robusta
- Dominando tipos de datos en Python: Guía práctica
- Dominando operadores en Python: Guía completa
- Dominando la sentencia pass en Python: Guía práctica
- Dominando Diccionarios en Python: Creación, Manipulación y Técnicas Avanzadas
- Dominando Excepciones Personalizadas en Python: Guía Práctica
- Dominando la Programación Orientada a Objetos en Python: Clases, Herencia, Encapsulación y Polimorfismo
- Dominando la Herencia en Python: Conceptos, Sintaxis y Ejemplos Prácticos
- Entendiendo type() e isinstance() en Python: ejemplos prácticos
- Patrón Singleton en Java explicado: Cómo implementarlo y usarlo de forma segura