Introducción a la Programación Orientada a Objetos(OOP)

Guía básica para el uso de Clases y Objetos usando Python

Alvison Hunter
10 min readJun 2, 2021
Programación Orientada a Objetos (OOP) — Imagen tomada del portal de RealPython

Python y la Programación Orientada a Objetos (OOP)

La Programación Orientada a Objetos (OOP), es un paradigma de programación que proporciona un medio para estructurar programas de modo que las propiedades y los comportamientos se agrupen en objetos individuales.

Por ejemplo, un objeto podría representar a una persona con propiedades como nombre, edad y dirección y comportamientos como caminar, hablar, respirar y correr. O podría representar un correo electrónico con propiedades como una lista de destinatarios, asunto y cuerpo y comportamientos como agregar archivos adjuntos y enviar.

Dicho de otra manera, la Programación Orientada a Objetos (Object Oriented Programming), es un enfoque para modelar cosas concretas del mundo real, como automóviles, así como relaciones entre cosas, como empresas y empleados, estudiantes y profesores, etc. Este tipo de Programación modela entidades del mundo real como objetos de software que tienen algunos datos asociados y pueden realizar ciertas funciones.

Otro paradigma de programación común es la programación procedimental, que estructura un programa como una receta en el sentido de que proporciona un conjunto de pasos, en forma de funciones y bloques de código, que fluyen secuencialmente para completar una tarea.

El punto mas importante es que los objetos están en el centro de la Programación Orientada a Objetos (Object Oriented Programming), no solo representando los datos, como en la programación procedimental, sino también en la estructura general del programa.

¿Por qué debemos usar Object Oriented Programming(OOP)?

Los desarrolladores a menudo eligen usar Programación Orientado a Objetos(OOP) en sus programas con Python porque hace que el código sea más reutilizable y facilita el trabajo con programas más grandes. Dichos programas ayudan al desarrollador a evitar repetir código porque una clase puede definirse una vez y reutilizarse muchas veces.

Python es un lenguaje de Programación Orientado a Objetos(OOP) la cual es una forma muy popular de crear software. A diferencia de la programación orientada a procedimientos, donde el énfasis principal está en las funciones, la programación orientada a objetos enfatiza los objetos.

Con la OOP puedes hacer que tu programa sea mucho más organizado, escalable, reutilizable y extensible. Sin embargo, el concepto deProgramación Orientado a Objetos(OOP) puede resultar un poco extraño para algunos developers. Puede ser difícil de entender, pero te aseguro que es un concepto muy poderoso sin duda alguna.

Hablemos un poco de algunos elementos que conforman la Programación Orientado a Objetos(OOP) o la POO como la conocen algunos en Nicañol.

¿Cómo definimos clases con Python?

Al igual que las definiciones de funciones comienzan con la palabra clave def en Python, las definiciones de clase comienzan con una palabra clave class.

La primera cadena dentro de la clase se llama docstring y tiene una breve descripción sobre la clase. Aunque no es obligatorio, es muy recomendable ponerla por asuntos de documentación en general, pero no te preocupes que no pasa nada si no la pones, es sólo para hacer las cosas de la mejor forma.

Aquí hay una definición de clase sencillita, nada farandula, algo simple ya con el docstring incluido para que veas como se agrega este a nuestro codigo.?

class NicaraguanTypicalMeals:
''' This is the NicaraguanTypicalMeals class'''
pass

Una clase crea un nuevo namespace local donde se definen todos sus atributos. Los atributos pueden ser datos o funciones.

También contiene atributos especiales que comienzan con dos guiones bajos __. Para darles un ejemplo concreto de esto puedes probar con el __doc__ el cual nos da la cadena de documentación de alguna clase.

Tan pronto como definimos una clase, se crea un nuevo objeto de clase con el mismo nombre. Este objeto de clase nos permite acceder a los diferentes atributos, así como crear instancias de nuevos objetos de esa clase.

Un ejemplo de clases que incluye tambien un metodo el cual se usara para saludar al Python dev, seria algo como lo planteado en el siguiente snippet:

Clases versus Instancias

Las clases se utilizan para crear estructuras de datos definidas por el usuario. Las clases definen funciones llamadas métodos, que identifican los comportamientos y acciones que un objeto creado a partir de dicha clase, puede realizar con sus datos. Veamos un ejemplo de una clase:

Como ves en este ejemplo, una clase es un modelo de cómo se debe definir algo. En realidad, no contiene ningún dato. La clase Dog especifica que un nombre, una edad y una raza son necesarios para definir un perro, pero no contiene el nombre, edad o la raza de ningún perro en específico.

Mientras que la clase es el blueprint, una instancia es un objeto que se construye a partir de una clase y contiene datos reales. Una instancia de la clase Dog ya no es un blueprint. Es un perro real con un nombre, como Chele, que tiene cuatro años y es de raza Belgiam Tervuren.

Dicho de otra manera, una clase es como un formulario o cuestionario. Una instancia es como un formulario que se ha llenado con información. Al igual que muchas personas pueden completar el mismo formulario con su propia información única, se pueden crear muchas instancias a partir de una sola clase, ¿Me comprendes, Méndez?.

¿Qué son los objetos en Python?

En Python, los desarrolladores pueden definir objetos. Un objeto es una colección de métodos y variables, los cuales viven en algún lugar de la memoria de la computadora. Dichos objects se pueden manipular en tiempo de ejecución.

En la OOP, Un objeto es una instancia de una clase. Como dije anteriormente, una clase viene a ser como un plano, mientras que una instancia es una copia de la clase con valores reales. Los objetos constas de los siguientes elementos:

Estado: está representado por los atributos de un objeto. También refleja las propiedades de un objeto.
Comportamiento: está representado por los métodos de un objeto. También refleja la respuesta de un objeto a otros objetos.
Identidad: le da un nombre único a un objeto y permite que un objeto interactúe con otros objetos.

Declarando objetos (también llamado instanciar una clase)

Cuando se crea un objeto de una clase, se dice que se crea una instancia de la clase. Todas las instancias comparten los atributos y el comportamiento de la clase. Pero los valores de esos atributos, es decir, el estado, son únicos para cada objeto. Una sola clase puede tener cualquier número de instancias.

Para mostrarles un poco de esto, creemos un ejemplo teórico un poco fuera de lo normal, hablando de comidas Nicaraguenses populares como valores de los atributos de esta clase. Luego definiremos un objeto de la clase NicaraguanTypicalMeals.

Para crear un objeto, declaremos la clase de la cual heredaremos las características de esta instancia. Luego accederemos a esas propiedades heredadas imprimiendo en pantalla cada una de ellas.

En Python nos basta solo unas líneas de código para lograr hacer esto:

Como pudimos ver, una clase es un modelo para ese objeto NicaraguanTypicalMeals que acabamos de construir. Podemos pensar en que una clase es como un boceto (prototipo) de una casa. Contiene todos los detalles sobre los pisos, puertas, ventanas, etc. Basándonos en estas descripciones construimos la casa. La casa es el objeto.

Asi como se pueden hacer muchas casas a partir del plano de una casa, podemos crear muchos objetos a partir de una clase. Un objeto también se denomina instancia de una clase y el proceso de creación de este objeto se denomina instanciación y lo escucharas mucho en la OOP, asi que te recomiendo recordar bien esto, estimado colega.

Creando un objeto en Python

Vimos que el objeto de clase podría usarse para acceder a diferentes atributos. También se puede utilizar para crear nuevas instancias de objetos lo que conocemos tambien como instanciación de esa clase, la cual mencionamos anteriorment. El procedimiento para crear un objeto es similar a la llamada a una función.

PythonZealot01 = PythonZealot()

Esto creará una nueva instancia de objeto llamada PythonZealot01. Podemos acceder a los atributos de los objetos usando el prefijo del nombre del objeto.

Los atributos pueden ser datos o métodos. Los métodos de un objeto son funciones correspondientes de esa clase. Esto quiere decir que dado a que PythonZealot01.sayHello es un objeto de función (o un atributo de clase) entonces PythonZealot01.sayHello será un objeto de tipo método.

Usando las Properties, los Getters y los Setters en Clases

En Python, los getters y setters no son los mismos que los de otros lenguajes de programación orientados a objetos. Básicamente, el objetivo principal de utilizar getters y setters en programas orientados a objetos es garantizar la encapsulación de datos. Las variables privadas en Python no son en realidad campos ocultos como en otros lenguajes orientados a objetos. Por lo general, los Getters y Setters en Python se usan a menudo cuando:

  • Necesitamos agregar lógica de validación para obtener y establecer un valor.
  • Para evitar el acceso directo a un campo de clase, es decir, las variables privadas no pueden ser accedidas directamente o modificadas por un usuario externo.

Pero, ¿qué es un Getter y un Setter, en resumen? Veamos entonces como podemos definir cada uno de estos métodos teóricamente hablando:

Getters: Estos son los métodos utilizados en la Programación Orientada a Objetos (OOP) que ayuda a acceder a los atributos privados de una clase.

Setters: Estos son los métodos utilizados en la Programación Orientada a Objetos (OOP) que ayudan a establecer el valor de los atributos privados en una clase.

- Atributos Privados y Encapsulacion en los Objetos

Veamos ahora cómo podemos proceder rápidamente a implementar un atributo privado de clase usando para esto python:

En este ejemplo vemos claramente que la clase Developer tiene tres métodos.

__init __: — Se utiliza para inicializar los atributos o propiedades de una clase.
__name: Este es un atributo privado.
get_name: Se usa para obtener los valores del atributo privado name.
set_name: Se usa para establecer el valor de name usando un objeto de una clase.
No puede acceder a las variables privadas directamente en Python. Es por eso que implementó el método getter.

¿Sigues confundido acerca de la funcionalidad de la clase? déjame explicarte esto brevemente y no te preocupes si no comprendes todo porque toma cierto tiempo saborearla pero vale la pena hacerlo, mi estimado lector.

Así es como se logra implementar atributos privados, getters y setters en Python. Escribamos la misma implementación pero de manera Pitónica.

En la manera Pitónica, no se necesita ningún método getters o setters para acceder o cambiar los atributos. Puede acceder a él directamente usando el nombre de los atributos.

¿Me estás diciendo que la manera Pitónica es aún más fácil sin tener que usar getters y setters? Mmm….No exactamente, mi estimado colega. Veamos esto con el siguiente ejemplo para aclarar esta duda.

¿Cuál es la diferencia que hay entre las dos clases citadas anteriormente?
Developer oculta los métodos y atributos privados. Implementa la función de encapsulación que es propia de la Programación Orientado a Objetos(OOP).

En cambio la clase PythonicWay no oculta los datos. No implementa ninguna función de encapsulación de la Programación Orientado a Objetos(OOP).

¿Cuál es la forma más recomendada de utilizar en este tipo de escenarios para cualquier desarrollador moderno?
Para ser honesto, todo depende de nuestra necesidad al estar resolviendo el problema. Si deseas atributos y métodos privados, puedes implementar la clase usando para ellos los métodos setters y getters, de lo contrario, lo puedes implementar de la manera Pitónica.

¿Cuándo vamos a hablar sobre el decorador @property?

Lo haremos ahora mismo: ¿Qué sucede si desea tener algunas condiciones para establecer el valor de un atributo en la clase Developer?

Digamos que si el valor que pasamos para el atributo name es igual a la cadena “Alvison Hunter”, podemos establecerlo en el atributo; de lo contrario, establecer el valor por defecto nosotros directamente en este método.

Implementemos esto cambiando el método set_name() en Developer. Revisemos para esto la clase creando un objeto y una vez teniendo la instancia probaremos hacer este cambio.

Todo se ve bien, funciona correctamente, sin embargo, existe una forma más apropiada para hacer esto. Veamos cómo implementar la clase anterior usando para ello el @property decorator.

NOTA: Escribiré sobre decorators en las clases en artículos futuros pero por el momento revisamos el decorador property. Si deseas más información sobre los decorators, te invito a ver este video donde se explica de forma simple como usarlos con Python.

El @property Decorator:

En este ejemplo, podemos ver que @property se usa para obtener el valor de un atributo privado sin usar ningún método de obtención(getter). Es importante mencionar que tenemos que poner una línea @property delante del método donde devolvemos la variable privada.

Para establecer el valor de la variable privada, usamos la forma de @method_name.setter delante del método. Tenemos que usarlo como nuestro setter.

@language.setter establecerá el valor de language comprobando las condiciones que hemos mencionado en el método. Otra forma de utilizar la propiedad es la siguiente:

En este ejemplo vemos que se pasan todos los métodos getter y setter al método property y luego se asigna el resultado a una variable que debe usarse como atributo de clase, que en este caso le llamamos language.

Cabe señalar que los métodos setter y getter tienen que ser privados para ocultarlos a como se muestra en el ejemplo.

Conclusión
Bueno, creo que ya hemos logrado cubrir un poco sobre Object Oriented Programming y logramos también implementar la encapsulación en Python de forma básica y a la vez hemos plasmado de manera simple la diferencia que existen entre el uso de setter, getter y el property decorator cuando creamos nuestras clases.

Cabe mencionar que la mayoría de los lenguajes de programación modernos, como Java, C# y C++, entre otros, siguen los principios de Programación Orientada a Objetos (OOP), por lo que lo mencionado aquí será también, hasta cierto punto, aplicable a algunos de ellos sin importar a dónde vayas actualmente con respecto a tu carrera o cual sea tu lenguaje predilecto para programar.

NOTA: Nuestro Canal de YouTube está siempre a sus ordenes, colegas! Si estás comenzando con Python o JavaScript, o si simplemente te gusta la programación web en general, te recomiendo que le eches un vistazo a mi Canal de YouTube donde comparto tips sobre estos lenguajes, así como muchos ejemplos con código incluido el cual compartimos de manera gratuita para ayudarte en este hermoso camino del desarrollo del software.

Nuestro Canal de YouTube esta siempre a sus ordenes, estimad@s colegas!

👏 Claps si disfrutaste este articulo, así podré motivarme a escribir mas!
🤔 Comenta si tienes algo que decir, es muy importante saber tu opinión.
🙂 Click en seguir Alvison para que estes al tanto de mis nuevos artículos!

Hasta la próxima ocasión, mis estimados lectores!

--

--

Alvison Hunter

JavaScript & Python Developer | Managing Partner @CodeCraftersLabs. Linguist Enthusiast & Music Connoisseur | Husband | Proud Father of 2 brave warriors.🙈🙉🙊