Hablamos acerca de atributos privados en Python.
Comencemos con la pregunta obligada ¿Qué es un atributo privado? En términos simples una atributo privado no es más que un atributo el cual solo puede ser utilizando dentro de la clase. 🤠
En algunos lenguajes de programación orientada a objetos (Java por ejemplo), para que un atributo pueda ser considerado privado, se utiliza algún tipo de palabra reservada, comúnmente private.
Sin embargo en Python no existe como tal dicha palabra reservada, y esto es debe por el simple hecho que en Python no existen los atributos privados. Sí, así como lo lees. 😯
En Python todos los atributos asociados a un objetos serán públicos. Esto quiere decir que los atributos podrán ser consultados, actualizados o eliminados desde cualquier parte del código. En condiciones, ciclos, métodos, paquetes, módulos etc...
En primera instancia esto no suena a una muy buena idea. Dejar que tu objeto puede ser gestionado por cualquier parte del código ya suena a algo muy peligroso. Un hueco potencial de seguridad. 🚨
A afortunadamente el lenguaje implementa el mecanismo name mangling para poder simular crear atributos privados.
Verás, en Python para que un atributo, o método, puede ser considerado "privado" debe poseer el prefijo doble guion bajo (__). 🐍
Veamos un par de ejemplos.
class User:
def __init__(self, username):
self.__username = username
def __private_method(self):
print('Este es un método privado')
Para este ejemplo he definido el atributo username y el método private_method como privados. Es decir, un atributo y un método que solo pueden ser utilizados dentro de la clase donde fueron creados.
Si intentamos acceder al atributo, o ejecutar el método privado, obtendremos un error
py = User('PyWombat')
print(py.__username)
Traceback (most recent call last):
File "main.py", line 11, in <module>
print(py.__username)
AttributeError: 'User' object has no attribute '__username'
Donde se nos indique que, el atributo/método no se encuentra definido. 🔥
Sin embargo, si intentamos utilizar los atributos y métodos privados en un método publico (Dentro de la clase) no obtendremos ningún tipo de error.
class User:
def __init__(self, username):
self.__username = username
def __private_method(self):
print('Este es un método privado')
def public_method(self):
print(self.__username)
self.__private_method()
py = User('PyWombat')
py.public_method()
Salida.
PyWombat
Este es un método privado
Perfecto 😎 nuestra clase es mucho más robusta y segura, implementamos encapsulamiento. Bueno, algo así.
Doble guion bajo (__)
Con el uso del doble guion bajo (__) le indicamos al interprete de Python que sobrescriba el nombre de los atributos y métodos, esto con la finalidad de evitar conflictos con el namespace.
Si examinamos los atributos del objeto podremos percatarnos que, todos aquellos atributos con un doble guion bajo (__) como prefijo, el interprete les ha cambiado el nombre. 😯
>>> py = User('PyWombat')
>>> print(py.__dict__)
{'_User__username': 'PyWombat'}
Nota: Si quieres conocer más acerca de los atributos de un objeto te invito a que le eches un vistazo al siguiente artículo.
Ahora se almacena, internamente, el atributo con la siguiente estructura en su nombre: _<Clase>__<Atributo>
Por lo cual, si intentamos acceder a los atributos, y método, con esta estructura no obtendremos ningún tipo de error. 😵
>>> py = User('PyWombat')
>>> print(py._User__username)
>>> py._User__private_method()
Salida.
PyWombat
Este es un método privado
Vaya, y no solo podemos acceder a los atributos, también podemos modificarlos.
>>> py._User__username = 'Cambio de username'
>>> py._User__username
'Cambio de username'
De igual forma, para confirmar esto, podemos hacer uso de la función dir.
>>> dir(py)
Esto para conocer todos los métodos que posee el objeto.
Algo muy curioso, y peligroso ¿No lo crees? 🐛
Conclusión
Como pudimos aprender en este post, en Python no existen como tal los atributos y métodos privados. Sin bien podemos simular su uso, hay que tener en cuenta que no existe un mecanismo que impida que partes del código, externas a la clase, accedan, modifique o eliminen este tipo de atributos.
El uso del doble guion bajo (__) es un claro indicador, para nosotros como desarrolladores, que el atributo/método es "Privado" y por lo tanto debemos abstenernos de usarlo fuera de la clase. Código de etiqueta entre programadores. 🧐🍸
PD
Para continuar con esta serie de artículos te recomiendo le eches un vistazo a los siguientes artículos relacionados.