Herramientas de usuario

Herramientas del sitio


informatica:programacion:python:poo

Python: Programación Orientada a Objetos

Python permite el usos de clases para organizar mejor el código y modelar objetos del mundo real mediante código.

En Python todo es un objeto. El tipo más básico de objeto en Python es object. Las clases que creemos serán subclases de object, por lo que object será la superclase de todo el resto de clases.

Una clase en Python representa objetos del mundo real mediante la unión de sus características con las acciones/funciones que pueden realizar esos objetos. Por ejemplo, un pájaro tiene características como pico, alas y patas. También realiza ciertas funciones como volcar o hacer sonidos.

En POO, las características/propiedades de un objeto se llama atributos y sus funciones/acciones métodos.

En Python podríamos hacer:

class pajaro:
    # Características, llamados métodos en POO
    alas = 2
    patas = 2
    pico = 1
 
    # Funciones, llamados métodos en POO
    def comer(self): 
        print("Estoy comiendo")
    def hacer_sonidos(self): 
        print("Estoy piando")      
    def volar(self): 
        print("Estoy volando")

Para nombrar una clase se sigue la siguiente nomenclatura: class nombreClase. Es decir, comenzamos con una letra minúscula y separamos cada palabra por una mayúscula. La palabra reservada class indica que estamos definiendo una clase.

Una vez que se crea una clase, podemos usarla sus atributos y funciones tantas veces como queramos mediante la creación de nuevos objetos de esa clase. Un objeto es una instancia de una clase. Para el ejemplo de los pájaros, podemos tener diferentes tipos de pájaro, todos tendrán comparten el mismo número de patas, alas y picos; pueden comer, piar y volar. Estas especies pueden ser objetos de la clase “pájaro”. Podríamos tener un objeto llamado “pájaro azul” y otro “gorrión”. Ambos objetos son instancias de la clase “pájaro”. ¿Cómo hacemos esto en Python?

pajaro_azul = pajaro()
gorrion = pajaro()

La sintaxis para definir un objeto en Python:

nombreObjeto = nombreClase()

Si queremos saber cuántas patas tiene el pájaro azul:

print(pajaro_azul.patas)

Si queremos que vuele, es decir, que use el método correspondiente:

gorrion.volar()

Si queremos objener información sobre los atributos de un objeto, creamos un método de clase para ello:

class pajaro:
    alas = 2
    patas = 2
    pico = 1
 
    def comer(self): 
        print("Estoy comiendo")
    def hacer_sonidos(self): 
        print("Estoy piando")      
    def volar(self): 
        print("Estoy volando")
    def hablar(self):
        print("Hola, soy un pájaro. Tengo %s alas, %s patas y %s pico" % (self.alas, self.patas, self.pico))

Debemos usar self para que el método correspondiente sepa a qué objeto pertenene el atributo que queremos. El parámetro self es como un placeholder temporal, almacena el propio objeto. Cuando un método del objeto es llamado, el propio objeto es pasado como argumento al método y mostrado en una variable llamada self, por eso siempre tenemos que usar self como primero argumento de los métodos de clase en Python. Esto también permite al método poder acceder a otros métodos y atributos del objeto.

La función init() es un método de clase que inicializa ciertas variables o tareas que se harán tan pronto como se cree un objeto:

class pajaro:
    alas = 2
    patas = 2
    pico = 1
 
    def __init()__(self, nombre, peso, color):
        self.especie = nombre
        self.peso = peso
        self.color = color
 
    def comer(self): 
        print("Estoy comiendo")
    def hacer_sonidos(self): 
        print("Estoy piando")      
    def volar(self): 
        print("Estoy volando")
    def hablar(self):
        print("Hola, soy un %s. Tengo %s alas, %s patas y %s pico" % (self.specie, self.alas, self.patas, self.pico))
        print("Peso %s gramos y soy de color %s " % (self.peso, self.color))

A la hora de crear el objeto:

gorrion = pajaro('gorrion', ''20'', 'marrón')

Podemos añadir otras cosas en el momento de creación del objeto. Por ejemplo:

# (...)
    def __init()__(self, nombre):
        self.especie = nombre
        self.peso = peso
        self.color = color        
        print("Creando el objeto %s", % self.especie)

De esa manera, cada vez que creemos un objeto, se imprimirá también ese mensaje.

Si no fuese por las clases, tendríamos que crear diferentes variables y funciones por cada tipo de pájaro que queramos. Las clases y los objetos reducen así la repetición de código.

Todo es un objeto

En Python todo es un objeto. Incluso cuando definimos una cadena de texto:

s = "hola"

Estamos creando un objeto de la clase String (ya incluida en Python). Podemos comprobarlo:

print(type(s))
 
# <class 'str'>

Como objeto, tiene sus atributos y métodos. Con la función dir podemos ver los métodos disponibles:

dir(s)
 
# ['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']

Clases

Son el modelo que nos permite crear objetos.

class Coche(object):
 
    # Constructor de la clase
    def __ini__(self, marca):
        # Ojo, este atributo es distinto que el argumento
        self.marca = marca

El constructor permite dar una serie de valores iniciales a los objetos que se creen a partir de la clase.

Al pasarle a la clase object estamos heredando una clase incluida en Python llamada Object y nos proporcionará una serie de utilidades.

El parámetro self se utiliza para referirse al objeto que se crea, esa instancia en particular. No es obligatorio usar esa palabra, pero se utiliza por convención.

Atributos

Las propiedades de un objeto se pueden definir en cualquier sitio, pero lo recomendable es hacerlo al principio de la clase:

class Coche(object):
 
    ruedas = 4
 
    def __init__(self, marca):
        self.marca = marca

Creando un objeto y accediendo a sus propiedades:

c1 = Coche('Renault')
 
print(c1.ruedas) # 4

Podemos modificar las propiedades del objeto:

c1.ruedas = 6
 
print(c1.ruedas) # 6

Métodos

(...)
 
    def info(self):
        print("Marca de este coche: %s", % self.marca")
        

Uso:

c1 = Coche('Renault')
 
c1.info()
 
# Marca de este coche: Renault

Creación de objetos

Crear un objeto a partir de una clase se conoce como instanciar una clase. Un objeto es una instancia de una clase.

Creando dos objetos de la misma clase:

c1 = Coche('Renault')
 
c2 = Coche('Ford')
 
print(c1.marca)
print(c2.marca)
 
# Renault
# Ford

Herencia

La herencia es un proceso que nos permite utilizar métodos definidos en otras clases sin tener que definirlos en nuestra clase. De esta manera se comparte la funcionalidad, atributos y métodos.

class Coche(object):
 
    def __init__(self):
        print("Acabas de crear una instancia de Coche")
 
    def arrancar(self):
        print("Coche arrancando...")
 
    def parar(self):
        print("Coche parado")

Creamos una clase heredada de la anterior:

class Renault(Coche):
 
    def __init__(self):
        # Llamamos al constructor de la clase padre
        Car.__init__(self)   
 
        print("Acabas de crear una instancia de Renault")

Ahora, desde la clase Renault, tendremos acceso también a los métodos de la clase Coche:

r = Renault()
 
r.arrancar()
 
r.parar()

Sobrescritura de métodos

Si queremos redefinir algún método de la clase padre, basta con definirlo con el mismo nombre en la clase heredada y darle la funcionalidad que queramos:

class Renault(Coche):
 
    def __init__(self):
        # Llamamos al constructor de la clase padre
        Car.__init__(self)   
 
        print("Acabas de crear una instancia de Renault")
 
    def arrancar(self):
        print("Arrancando el Renault")

Si quisiéramos hacer referencia a un método de la clase padre, utilizamos super:

(...)
    def arrancar(self):
        super().arrancar()
        print("Arrancando el Renault")

Imprimir la representación de un objeto

Python llama al método __str__ cuando utilizamos print sobre un objeto. Por defecto, mostrará algo como:

Si queremos decidir qué imprimirá, crearemos nosotros un método __str__ en nuestra clase:

class Coordenada(object):
    def__init__(self, x, y):
        self.x = x
        self.y = y
 
    def __str__(self):
        return "<" + str(self.x) + ", " + str(self.y) + ">"

__str__ debe devolver un string

Operadores especiales

Hay una serie de operadores que al utilizarlos en Python, llama a ciertos métodos de los objetos:

Método Operador
__add__ self + other
__sub__ self - other
__eq__ self == other
__lt__ self < other
__len__ len(self)
__str__ print(self)

Recursos

informatica/programacion/python/poo.txt · Última modificación: por tempwin