- En Python todo es un objeto
- Clases
- Variables/Métodos de clase
- Metodos privados
- None es null
- Test yourself!
La programación orientada a objetos (POO) es un paradigma de programación donde se programa pensando en objetos. Los objetos tienen un estado y una funcionalidad, y se relacionan entre ellos (unos usan otros, unos dependen de otros, etc).
Es algo inherente al lenguaje de programación. Existen multitud de lenguajes orientados a Objetos: Java, C++, etc. Python sólo es uno de muchos.
Algo particular de Python, es que todo es un objeto, incluso las funciones lo son.
def mi_funcion(x, y):
return x + y
print(type(mi_funcion))
Si ejecutamos el ejemplo anterior verás que la clase de mi_funcion es <class 'function'>. ¿Y que es eso de clase 🤔? Los objetos vienen definidos por una clase. Esta no es mas que un esquema donde definimos los atributos del objeto (define su estado) y sus funciones (define su comportamiento).
# Esto es pseudocodigo, ¡no Python!
Persona {
nombre
apellidos
edad
getNombre() {
return nombre
}
}
En ejemplo anterior tenemos la clase Persona con tres atributos y un método.
En el caso de la funcion, su clase es Function.
Para crear clases en Python lo haríamos de la siguiente forma:
class Persona:
#...
Como podeis ver se usa la palabra clave class e indicamos el nombre de la clase. Para poder crear una instancia de la clase, tenemos que añadir un constructor:
class Persona:
# Constructor de la clase Persona
def __init__(self, nombre, edad):
self.nombre = nombre
self.edad = edad
- Hemos creado la clase Persona.
- Tiene un constructor que recibe dos argumentos: nombre y edad
- Al hacer self. estamos añadiendo atributos a la clase. En este caso, nombre y edad.
Además del constructor, podemos añadir otros métodos:
class Persona:
# Constructor de la clase Persona
def __init__(self, nombre, edad):
self.nombre = nombre
self.edad = edad
def one_function(self):
return self.edad * 5
- Hemos añadido un método one_function.
self es una palabra clave para referirse a mi misma instancia
Si os fijáis, tanto en el constructor como en la función hemos añadido self como argumento. Es un requisito de Python para dentro de la función/constructor poder acceder a los atributos de la clase.
Veamos un ejemplo:
class Persona:
# Constructor de la clase Persona
def __init__(self, nombre, edad):
self.nombre = nombre
self.edad = edad
def one_function(self):
return self.edad * 5
jorge = Persona('Jorge', 25) # llamada al constructor de Persona
print(jorge.one_function()) # imprime 125
jorge.edad = 10 # hemos modificado el valor de edad en la instancia de jorge
En el apartado anterior hemos visto atributos y métodos de instancia, es decir, para poder acceder a ellos necesitamos crear una instancia de la clase.
En python, existen las variables estáticas que se definen fuera de cualquier método de la clase:
class Persona:
saludo = 'Hola mundo'
print(Persona.saludo) # imprime Hola Mundo
Tambien existen los métodos de clase y estáticos:
class Persona:
@classmethod
def metodo_de_clase(cls):
print('Hola, soy un metodo de clase')
@staticmethod
def metodo_estatico():
print('Hola, soy un metodo estatico, por lo que no se pasa cls')
Persona.metodo_de_clase()
Persona.metodo_estatico()
@classmethod y @staticmethod son decoradores. Es un modo de indicarle a Python el tipo de función. Como ves en ambos casos podemos llamar a los métodos sin instanciar la clase.
La diferencia entre ellos está en que el método de clase, recibe cls como argumento, mientras que el estatico no (sería el equivalente a static method en Java). Hemos visto antes que self es la palabra clave que se usa para referirse a la propia instancia (al objeto), en cambio cls es usada por convención (puede usarse otro nombre) para referirse a la copia del prototipo de la clase
Si quieres saber más de @classmethod, mira el siguiente enlace.
Si quieres saber más de @staticmethod, mira el siguiente enlace.
Un método privado es aquel sólo accesible dentro de la propia clase. Se usa para definir métodos auxiliares que no necesitamos exponer fuera de la clase (esto se llama encapsulación).
Los métodos privados como tal no existen en Python. En Java tenemos la palabra clave private para declarar un método como privado. En python lo equivalente es lo siguiente:
class Persona:
def metodo_publico(self):
print('dentro del metodo_publico')
self.__metodo_privado()
pass
def __metodo_privado(self):
print('dentro del __metodo_privado')
pass
Como ves la diferencia esta en el que nombre empieza por __(dos guiones bajos).
Si lo probamos, verás que no puedes llamar a __metodo_privado:
persona = Persona()
persona.metodo_publico()
persona.__metodo_privado() # Lanza un error
En cambio podemos llamarlo realmente:
persona._Persona__metodo_privado() # ¡Estamos llamando al método privado!
Por este motivo, realmente no es un método privado 🤠.
Una instancia no es más que una referencia a una dirección de memoria, una variable que apunta a un objeto. Puede ser que tengamos una variable vacia, es decir, que no apunte a ninguna dirección de memoria (Un string vacio si ocupa memoria 👍).
Para representar eso, existe el tipo None en Python:
no_ocupo_memoria = None
print(type(no_ocupo_memoria)) # imprime <class 'NoneType'>
En este laboratorio os proponemos el siguiente reto:
Crear una clase Hero con cuatro atributos: nombre, sexo, saludo y nivel (del 1 al 100). Crea varios personajes y crea un método lucha que recibirá dos parámetros, de tipo Hero y en base al nivel de poder mostrará un saludo o otro. Por cierto comprueba que los parámetros no sean nulos.
Este laboratorio ha sido denso, pero hemos conseguido ser expertos en POO. En el siguiente le toca el turno a las excepciones ❎.