Python nos da la capacidad de crear métodos 'privados' y variables dentro de una clase anteponiendo doble subrayado al nombre, así: __myPrivateMethod()
. ¿Cómo, entonces, se puede explicar esto?
>>> class MyClass:
... def myPublicMethod(self):
... print 'public method'
... def __myPrivateMethod(self):
... print 'this is private!!'
...
>>> obj = MyClass()
>>> obj.myPublicMethod()
public method
>>> obj.__myPrivateMethod()
Traceback (most recent call last):
File "", line 1, in
AttributeError: MyClass instance has no attribute '__myPrivateMethod'
>>> dir(obj)
['_MyClass__myPrivateMethod', '__doc__', '__module__', 'myPublicMethod']
>>> obj._MyClass__myPrivateMethod()
this is private!!
¡¿Cual es el trato?!
Explicaré esto un poco para aquellos que no lo entendieron.
>>> class MyClass:
... def myPublicMethod(self):
... print 'public method'
... def __myPrivateMethod(self):
... print 'this is private!!'
...
>>> obj = MyClass()
Lo que hice allí fue crear una clase con un método público y un método privado e instanciarlo.
A continuación, llamo a su método público.
>>> obj.myPublicMethod()
public method
A continuación, intento llamar a su método privado.
>>> obj.__myPrivateMethod()
Traceback (most recent call last):
File "", line 1, in
AttributeError: MyClass instance has no attribute '__myPrivateMethod'
Todo se ve bien aquí; No podemos llamarlo. Es, de hecho, 'privado'. Bueno, en realidad no lo es. Ejecutar dir () en el objeto revela un nuevo método mágico que Python crea mágicamente para todos sus métodos 'privados'.
>>> dir(obj)
['_MyClass__myPrivateMethod', '__doc__', '__module__', 'myPublicMethod']
El nombre de este nuevo método siempre es un guión bajo, seguido del nombre de la clase, seguido del nombre del método.
>>> obj._MyClass__myPrivateMethod()
this is private!!
Demasiado encapsulado, ¿eh?
En cualquier caso, siempre escuché que Python no admite la encapsulación, entonces, ¿por qué intentarlo? ¿Lo que da?
Respuestas:
La codificación del nombre se utiliza para garantizar que las subclases no anulen accidentalmente los métodos y atributos privados de sus superclases. No está diseñado para evitar el acceso deliberado desde el exterior.
Por ejemplo:
Por supuesto, se descompone si dos clases diferentes tienen el mismo nombre.
fuente
Ejemplo de función privada.
fuente
self = MyClass()
self.private_function()
. : D Por supuesto que no funciona en clases, pero solo tienes que definir una función personalizada:def foo(self): self.private_function()
function_call.startswith('self.')
.inspect.stack()[1][4][0].strip()
<- ¿Cuáles son esos números mágicos 1, 4 y 0?self = MyClass(); self.private_function()
y falla cuando se llama usandox = self.private_function()
dentro de un método.Cuando llegué por primera vez de Java a Python, odiaba esto. Me dio mucho miedo.
Hoy podría ser lo único que más me gusta de Python.
Me encanta estar en una plataforma, donde las personas confían unas en otras y no sienten que necesitan construir muros impenetrables alrededor de su código. En lenguajes fuertemente encapsulados, si una API tiene un error y ha descubierto lo que sale mal, es posible que aún no pueda solucionarlo porque el método necesario es privado. En Python la actitud es: "seguro". Si crees que entiendes la situación, quizás incluso la hayas leído, entonces todo lo que podemos decir es "¡buena suerte!"
Recuerde, la encapsulación ni siquiera está débilmente relacionada con la "seguridad" o con mantener a los niños fuera del césped. Es solo otro patrón que debe usarse para hacer que una base de código sea más fácil de entender.
fuente
De http://www.faqs.org/docs/diveintopython/fileinfo_private.html
fuente
La frase que se usa comúnmente es "aquí todos aceptamos adultos". Al anteponer un solo guión bajo (no exponer) o doble guión bajo (ocultar), le está diciendo al usuario de su clase que pretende que el miembro sea 'privado' de alguna manera. Sin embargo, confía en que todos los demás se comporten de manera responsable y respeten eso, a menos que tengan una razón convincente para no hacerlo (por ejemplo, depuradores, finalización de código).
Si realmente debe tener algo privado, puede implementarlo en una extensión (por ejemplo, en C para CPython). Sin embargo, en la mayoría de los casos, simplemente aprende la forma pitónica de hacer las cosas.
fuente
No es que usted no pueda evitar la privacidad de los miembros en ningún lenguaje (aritmética de puntero en C ++, Reflexiones en .NET / Java).
El punto es que obtiene un error si intenta llamar al método privado por accidente. Pero si quieres dispararte en el pie, adelante y hazlo.
Editar: No intentas asegurar tus cosas mediante la encapsulación OO, ¿verdad?
fuente
La
class.__stuff
convención de nomenclatura le permite al programador saber que no debe acceder__stuff
desde afuera. El cambio de nombre hace improbable que alguien lo haga por accidente.Es cierto que aún puede solucionar esto, es incluso más fácil que en otros lenguajes (que por cierto también le permite hacer esto), pero ningún programador de Python haría esto si se preocupa por la encapsulación.
fuente
Un comportamiento similar existe cuando los nombres de los atributos del módulo comienzan con un guión bajo (por ejemplo, _foo).
Los atributos del módulo nombrados como tales no se copiarán en un módulo de importación cuando se utilice el
from*
método, por ejemplo:Sin embargo, esta es una convención y no una restricción de idioma. Estos no son atributos privados; pueden ser referenciados y manipulados por cualquier importador. Algunos sostienen que debido a esto, Python no puede implementar una verdadera encapsulación.
fuente
Es solo una de esas opciones de diseño de lenguaje. En cierto nivel están justificados. Lo hacen para que tengas que esforzarte mucho para intentar llamar al método, y si realmente lo necesitas tanto, ¡debes tener una buena razón!
Los ganchos de depuración y las pruebas vienen a la mente como posibles aplicaciones, por supuesto, utilizadas de manera responsable.
fuente
Con Python 3.4 este es el comportamiento:
https://docs.python.org/3/tutorial/classes.html#tut-private
Incluso si la pregunta es antigua, espero que mi fragmento pueda ser útil.
fuente
La preocupación más importante sobre los métodos y atributos privados es decirles a los desarrolladores que no lo llamen fuera de la clase y esto es encapsulación. uno puede malinterpretar la seguridad de la encapsulación. cuando uno deliberadamente usa una sintaxis como esa (abajo) que mencionó, no desea la encapsulación.
He migrado de C # y al principio también fue extraño para mí, pero después de un tiempo llegué a la idea de que solo la forma en que los diseñadores de código de Python piensan sobre OOP es diferente.
fuente
Según tengo entendido, no pueden ser privados. ¿Cómo se puede hacer cumplir la privacidad?
La respuesta obvia es "solo se puede acceder a los miembros privados
self
", pero eso no funcionaría:self
no es especial en Python, no es más que un nombre de uso común para el primer parámetro de una función.fuente