Although in Python all elements within a class are public by default, there is a way to emulate a certain degree of privacy for them by using two underscores at the beginning of the method or attribute name, eg: __contraseña
. This really just renames the attribute to avoid collisions with internal Python methods, such as the method __init__
, and renames the attribute by appending it _NombreClase
to the beginning, so that the attribute I used as an example would be _NombreClase__contraseña
. And if we called the object by its attribute, it would give us an error, although it would still be completely accessible if we make the call using the name that is automatically assigned to it, as seen in the following example:
class MiClase:
def __init__(self):
self.__privada = "Mensaje secreto"
def devuelve_privada(self):
return print(self.__privada)
objeto = MiClase()
objeto.devuelve_privada()
#>> Mensaje secreto
print(objeto._MiClase__privada)
#>> Mensaje secreto
objeto.__privada
#>> AttributeError: 'MiClase' object has no attribute '__privada'
Due to this, I thought that the private attributes of a class in Python were only intended to remind or make notice to the developers involved in a project that said attribute should not be changed lightly or that a specific method of the class should be used. to carry out said modification that performs controls or validations of some kind on the new value to be inserted. But then I came across this code which I have simplified a bit for the example:
class Usuario:
def __init__(self, usuario, contraseña):
self.__nombreUsuario = usuario
self.__contraseña = contraseña
def set_contraseña(self, contraseña):
self.__contraseña = contraseña
def get_contraseña(self):
return self.__contraseña
In this case of the creation of a new user, this practice is carried out in a context where no type of validation is carried out (already done previously) and everything indicates that it is used for security reasons, and I was wondering what type security can offer this. Due to the previously exposed vulnerability, knowing the name of the class and the attribute, its value can be changed. I also don't really understand why security measures should be created for this inside a code that runs on a server.
I feel like I'm not taking something into account, because those who did this are very experienced programmers and I'm sure they must have a valid reason for it.
You are taking everything into account and your knowledge is correct.
Using dunderscore (double underscore) in Python is used to call the Name Mangling rules , which is exactly how you explained at the beginning with the class
MiClase
.What it does is change the attribute
__privada
to_MiClase__privada
.Its only use cases as stated in PEP0008 are:
In the case of your class,
Usuario
I would say that the people who have developed it have done so with the aim of making the attributes "private". This is a bad practice in Python that is seen sometimes, since as you yourself have said they are not private.Since there are no private methods, the only thing you can do is make access to the methods/attributes as difficult as possible. But this is strongly discouraged as it will only make your code less readable.
We start from the point that the use of access modifiers (
private
,protected
,public
), do not respond to security reasons to prevent hackers, or unauthorized persons, from obtaining or altering any type of data in any language.Access modifiers serve a single purpose: Encapsulation. Its mission is to make the internal details of some class inaccessible, in order to prevent other entities in our code base from even knowing of its existence. This, in order to minimize the coupling between entities.
Furthermore, remember that the use of getters and setters has nothing to do with encapsulation. In fact, quite the opposite: they threaten the correct encapsulation of a class since they also expose internal details of the class. (More information on this can be found in this wonderful article, by Allen Holub: https://www.infoworld.com/article/2073723/why-getter-and-setter-methods-are-evil.html )
In other words, if the access modifiers protect us from anyone, it is from ourselves and our own teammates, from creating entities dependent on details, instead of dependent on abstractions and interfaces. Nothing more.
In Python, we certainly don't have a way to prevent access to or privatize certain members of a class. Here we trust the (famous) phrase "We are all consenting adults" . Basically, we follow conventions to note that certain members should not be overwritten, altered, or directly consumed. We sacrifice that strictness of language, to allow ourselves certain (albeit, personally, uncomfortable) liberties. You may like it, you may not, but it is the style of this great language.
Finally, remember that when it comes to web security measures, the measures to take have nothing to do with this issue. For example, in the case of Django, these measures include encrypting passwords, using Cross Site Request Forgery Protection, using an ORM to prevent things like SQL Injection, etc.
Not necessarily, or eventually yes. No, because as you have already seen, there is nothing private, in the style of for example Java, so any "evil" programmer could directly access the attribute without going through the "getters" or "setters". Eventually yes, if the project developers respect the convention of not using "private" attributes, either single or double underscore.
With respect to the code
set_contraseña()
andget_contraseña()
, certainly, since it does not have any validation and since the "strong" encapsulation that we could see, for example in Java, does not exist in Python, it is logical to ask the meaning of these functions. However, there may certainly be pre-established design patterns in the project or in the team, which establish basic "templates" that include the use of pseudo "getters" and/or "setters", also, that there are no validations today does not mean that there won't be any tomorrow, so we leave the place ready to incorporate them and lastly, it can be due to the real needs of the project, which imply that certain attributes are accessed through this mechanism.Accessing the private attributes of an object via getter/setter has at least two benefits.
The first is the ability to intercept variable accesses. Since all access is done via setter/getter, you have a place to add breakpoints and assert .
For example, let's say somewhere in the application someone is changing the password to
None
. With a setter, you can put a conditional breakpoint on the assignment:so that the execution is interrupted and you can go into the debugger to look at the call stack and the parameters involved.
You can also leave a
assert
to catch any strange cases:The other advantage is the ability to grow the application. For example, you can now add the requirement that the new one
password
must be different from the old one.Using setters you can enforce the restriction on the entire application just by changing the setter:
The function now returns
True
if the password passed validation and was updated.