Python – Orientado a Objetos

Anuncios

Python ha sido un lenguaje orientado a objetos desde que existe. Debido a esto, la creación y el uso de clases y objetos son francamente fáciles. Este capítulo le ayudará a convertirse en un experto en el uso del soporte de programación orientada a objetos de Python.

Si no tiene ninguna experiencia previa con la programación orientada a objetos (OO), es posible que desee consultar un curso de introducción a la misma o al menos un tutorial de algún tipo para que tenga una comprensión de los conceptos básicos.

Sin embargo, aquí hay una pequeña introducción de la programación orientada a objetos (POO) para ponerte al día –

Resumen de la terminología de la POO

  • Clase – Un prototipo definido por el usuario para un objeto que define un conjunto de atributos que caracterizan cualquier objeto de la clase. Los atributos son miembros de datos (variables de clase y variables de instancia) y métodos, a los que se accede mediante la notación de puntos.

  • Variable de clase – Una variable que es compartida por todas las instancias de una clase. Las variables de clase se definen dentro de una clase pero fuera de cualquiera de los métodos de la misma. Las variables de clase no se utilizan con tanta frecuencia como las variables de instancia.

  • Miembro de datos – Una variable de clase o de instancia que contiene datos asociados con una clase y sus objetos.

  • Sobrecarga de funciones – La asignación de más de un comportamiento a una función particular. La operación realizada varía según los tipos de objetos o argumentos implicados.

  • Variable de instancia – Una variable que se define dentro de un método y que pertenece sólo a la instancia actual de una clase.

  • Herencia – La transferencia de las características de una clase a otras clases que derivan de ella.

  • Instancia – Un objeto individual de una determinada clase. Un objeto obj que pertenece a una clase Círculo, por ejemplo, es una instancia de la clase Círculo.

  • Instanciación – La creación de una instancia de una clase.

  • Método – Un tipo especial de función que se define en la definición de una clase.

  • Objeto – Una instancia única de una estructura de datos que está definida por su clase. Un objeto comprende tanto los miembros de datos (variables de clase y variables de instancia) como los métodos.

  • Sobrecarga de operadores – La asignación de más de una función a un operador particular.

Creación de clases

La sentencia class crea una nueva definición de clase. El nombre de la clase sigue inmediatamente a la palabra clave class seguida de dos puntos como sigue –

class ClassName: 'Optional class documentation string' class_suite
  • La clase tiene una cadena de documentación, a la que se puede acceder a través de ClassName.__doc__.

  • El class_suite consiste en todas las sentencias de componentes que definen los miembros de la clase, los atributos de datos y las funciones.

Ejemplo

El siguiente es el ejemplo de una simple clase de 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
  • La variable empCount es una variable de clase cuyo valor se comparte entre todas las instancias de una esta clase. Se puede acceder a ella como Employee.empCount desde dentro de la clase o fuera de ella.

  • El primer método __init__() es un método especial, que se llama constructor de la clase o método de inicialización que Python llama cuando se crea una nueva instancia de esta clase.

  • Los demás métodos de la clase se declaran como funciones normales con la excepción de que el primer argumento de cada método es self. Python añade el argumento self a la lista por ti; no necesitas incluirlo cuando llames a los métodos.

Creación de Instancias de Objetos

Para crear instancias de una clase, llamas a la clase usando el nombre de la clase y le pasas los argumentos que acepte su método __init__.

"This would create first object of Employee class"emp1 = Employee("Zara", 2000)"This would create second object of Employee class"emp2 = Employee("Manni", 5000)

Acceso a Atributos

Accedes a los atributos del objeto usando el operador punto con objeto. Se accedería a la variable de la clase usando el nombre de la clase de la siguiente manera –

emp1.displayEmployee()emp2.displayEmployee()print "Total Employee %d" % Employee.empCount

Ahora, juntando todos los conceptos –

#!/usr/bin/pythonclass 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"This would create first object of Employee class"emp1 = Employee("Zara", 2000)"This would create second object of Employee class"emp2 = Employee("Manni", 5000)emp1.displayEmployee()emp2.displayEmployee()print "Total Employee %d" % Employee.empCount

Cuando se ejecuta el código anterior, produce el siguiente resultado –

Name : Zara ,Salary: 2000Name : Manni ,Salary: 5000Total Employee 2

Se pueden añadir, eliminar, o modificar los atributos de las clases y objetos en cualquier momento –

emp1.age = 7 # Add an 'age' attribute.emp1.age = 8 # Modify 'age' attribute.del emp1.age # Delete 'age' attribute.

En lugar de utilizar las sentencias normales para acceder a los atributos, puede utilizar las siguientes funciones –

  • El getattr(obj, name) – para acceder al atributo del objeto.

  • The hasattr(obj,name) – para comprobar si un atributo existe o no.

  • The setattr(obj,name,value) – para establecer un atributo. Si el atributo no existe, entonces será creado.

  • El delattr(obj, name) – para borrar un atributo.

hasattr(emp1, 'age') # Returns true if 'age' attribute existsgetattr(emp1, 'age') # Returns value of 'age' attributesetattr(emp1, 'age', 8) # Set attribute 'age' at 8delattr(empl, 'age') # Delete attribute 'age'

Atributos incorporados en la clase

Cada clase de Python mantiene los siguientes atributos incorporados y se puede acceder a ellos utilizando el operador punto como cualquier otro atributo –

  • __dict__ – Diccionario que contiene el espacio de nombres de la clase.

  • __doc__ – Cadena de documentación de la clase o ninguna, si no está definida.

  • __name__ – Nombre de la clase.

  • __module__ – Nombre del módulo en el que se define la clase. Este atributo es «__main__» en modo interactivo.

  • __bases__ – Una tupla posiblemente vacía que contiene las clases base, en el orden en que aparecen en la lista de clases base.

Para la clase anterior intentemos acceder a todos estos atributos –

#!/usr/bin/pythonclass 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.salaryprint "Employee.__doc__:", Employee.__doc__print "Employee.__name__:", Employee.__name__print "Employee.__module__:", Employee.__module__print "Employee.__bases__:", Employee.__bases__print "Employee.__dict__:", Employee.__dict__

Cuando se ejecuta el código anterior, produce el siguiente resultado –

Employee.__doc__: Common base class for all employeesEmployee.__name__: EmployeeEmployee.__module__: __main__Employee.__bases__: ()Employee.__dict__: {'__module__': '__main__', 'displayCount':<function displayCount at 0xb7c84994>, 'empCount': 2, 'displayEmployee': <function displayEmployee at 0xb7c8441c>, '__doc__': 'Common base class for all employees', '__init__': <function __init__ at 0xb7c846bc>}

Destrucción de Objetos (Recogida de Basura)

Python borra los objetos innecesarios (tipos incorporados o instancias de clases) automáticamente para liberar el espacio de memoria. El proceso por el cual Python recupera periódicamente bloques de memoria que ya no están en uso se denomina Recolección de Basura.

El recolector de basura de Python se ejecuta durante la ejecución del programa y se activa cuando el conteo de referencias de un objeto llega a cero. El recuento de referencias de un objeto cambia a medida que cambia el número de alias que apuntan a él.

El recuento de referencias de un objeto aumenta cuando se le asigna un nuevo nombre o se coloca en un contenedor (lista, tupla o diccionario). El recuento de referencias del objeto disminuye cuando se elimina con del, su referencia se reasigna, o su referencia sale del ámbito. Cuando la cuenta de referencias de un objeto llega a cero, Python lo recoge automáticamente.

a = 40 # Create object <40>b = a # Increase ref. count of <40> c = # Increase ref. count of <40> del a # Decrease ref. count of <40>b = 100 # Decrease ref. count of <40> c = -1 # Decrease ref. count of <40> 

Normalmente no te darás cuenta cuando el recolector de basura destruya una instancia huérfana y recupere su espacio. Pero una clase puede implementar el método especial __del__(), llamado destructor, que se invoca cuando la instancia está a punto de ser destruida. Este método podría ser utilizado para limpiar cualquier recurso de memoria no utilizado por una instancia.

Ejemplo

Este destructor __del__() imprime el nombre de la clase de una instancia que está a punto de ser destruida –

#!/usr/bin/pythonclass 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 = pt1pt3 = pt1print id(pt1), id(pt2), id(pt3) # prints the ids of the obejctsdel pt1del pt2del pt3

Cuando se ejecuta el código anterior, produce el siguiente resultado –

3083401324 3083401324 3083401324Point destroyed

Nota – Lo ideal es que defina sus clases en un archivo separado, y luego las importe en su archivo de programa principal utilizando la sentencia import.

Herencia de clases

En lugar de empezar desde cero, puede crear una clase derivándola de una clase preexistente, listando la clase padre entre paréntesis después del nombre de la nueva clase.

La clase hija hereda los atributos de su clase padre, y puede utilizar esos atributos como si estuvieran definidos en la clase hija. Una clase hija también puede sobrescribir miembros de datos y métodos de la clase padre.

Sintaxis

Las clases derivadas se declaran de forma muy similar a su clase padre; sin embargo, una lista de clases base para heredar se da después del nombre de la clase –

class SubClassName (ParentClass1): 'Optional class documentation string' class_suite

Ejemplo

#!/usr/bin/pythonclass Parent: # define parent class 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.parentAttrclass Child(Parent): # define child class def __init__(self): print "Calling child constructor" def childMethod(self): print 'Calling child method'c = Child() # instance of childc.childMethod() # child calls its methodc.parentMethod() # calls parent's methodc.setAttr(200) # again call parent's methodc.getAttr() # again call parent's method

Cuando el código anterior se ejecuta, produce el siguiente resultado –

Calling child constructorCalling child methodCalling parent methodParent attribute : 200

De manera similar, puede manejar una clase de múltiples clases padre como sigue –

class A: # define your class A.....class B: # define your class B.....class C(A, B): # subclass of A and B.....

Puede utilizar issubclass() o isinstance() funciones para comprobar una relación de dos clases e instancias.

  • La función booleana issubclass(sub, sup) devuelve true si la subclase sub dada es efectivamente una subclase de la superclase sup.

  • La función booleana isinstance(obj, Class) devuelve true si obj es una instancia de la clase Class o es una instancia de una subclase de Class

Sobreescritura de métodos

Siempre puede sobreescribir los métodos de su clase padre. Una de las razones para sobrescribir los métodos del padre es porque puede querer una funcionalidad especial o diferente en su subclase.

Ejemplo

#!/usr/bin/pythonclass Parent: # define parent class def myMethod(self): print 'Calling parent method'class Child(Parent): # define child class def myMethod(self): print 'Calling child method'c = Child() # instance of childc.myMethod() # child calls overridden method

Cuando se ejecuta el código anterior, produce el siguiente resultado –

Calling child method

Métodos de sobrecarga de base

La siguiente tabla enumera algunas funcionalidades genéricas que puede sobrescribir en sus propias clases –

Sr.No. Método, Descripción &Llamada de ejemplo
1

__init__ ( self )

Constructor (con cualquier argumento opcional)

Llamada de ejemplo : obj = className(args)

2

__del__( self )

Destructor, borra un objeto

Sample Call : del obj

3

__repr__( self )

Representación de cadena evaluable

Sample Call : repr(obj)

4

__str__( self )

Representación de cadena imprimible

Sample Call : str(obj)

5

__cmp__ ( self, x )

Comparación de objetos

Llamada de muestra : cmp(obj, x)

Sobrecarga de operadores

Supongamos que has creado una clase Vector para representar vectores bidimensionales, ¿qué ocurre cuando utilizas el operador más para sumarlos? Lo más probable es que Python te grite.

Sin embargo, podrías definir el método __add__ en tu clase para realizar la suma de vectores y entonces el operador más se comportaría según lo esperado –

Ejemplo

#!/usr/bin/pythonclass 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

Cuando se ejecuta el código anterior, produce el siguiente resultado –

Vector(7,8)

Ocultación de datos

Los atributos de un objeto pueden o no ser visibles fuera de la definición de la clase. Es necesario nombrar los atributos con un prefijo de doble guión bajo, y esos atributos entonces no son directamente visibles para los externos.

Ejemplo

#!/usr/bin/pythonclass JustCounter: __secretCount = 0 def count(self): self.__secretCount += 1 print self.__secretCountcounter = JustCounter()counter.count()counter.count()print counter.__secretCount

Cuando el código anterior se ejecuta, produce el siguiente resultado –

12Traceback (most recent call last): File "test.py", line 12, in <module> print counter.__secretCountAttributeError: JustCounter instance has no attribute '__secretCount'

Python protege esos miembros cambiando internamente el nombre para incluir el nombre de la clase. Puedes acceder a esos atributos como object._className__attrName. Si sustituyes la última línea por la siguiente, entonces te funcionará –

.........................print counter._JustCounter__secretCount

Cuando el código anterior se ejecuta, produce el siguiente resultado –

Deja una respuesta

Tu dirección de correo electrónico no será publicada.