Clase "privada"(implementación) en Python
design access-modifiers (7)
Estoy codificando un pequeño módulo de Python compuesto de dos partes:
- algunas funciones que definen una interfaz pública,
- una clase de implementación utilizada por las funciones anteriores, pero que no es significativa fuera del módulo.
Al principio, decidí "ocultar" esta clase de implementación definiéndola dentro de la función que la usa, pero esto dificulta la legibilidad y no se puede usar si múltiples funciones reutilizan la misma clase.
Entonces, además de los comentarios y las cadenas de documentos, ¿existe un mecanismo para marcar una clase como "privada" o "interna"? Soy consciente del mecanismo de subrayado, pero según lo entiendo, solo se aplica a variables, función y nombre de métodos.
Defina __all__
, una lista de nombres que desea exportar ( ver documentación ).
__all__ = [''public_class''] # don''t add here the ''implementation_class''
En breve:
No puedes hacer cumplir la privacidad . No hay clases privadas / métodos / funciones en Python. Al menos, privacidad no estricta como en otros idiomas, como Java.
Solo puede indicar / sugerir privacidad . Esto sigue una convención. La convención de python para marcar una clase / función / método como privada es para precederla con un _ (guión bajo). Por ejemplo,
def _myfunc()
oclass _MyClass:
También puede crear pseudo-privacidad prefabricando el método con dos guiones bajos (por ejemplo:__foo
). No puede acceder directamente al método, pero puede llamarlo a través de un prefijo especial utilizando el nombre de clase (por ejemplo:_classname__foo
). Entonces, lo mejor que puede hacer es indicar / sugerir privacidad, no hacerla cumplir.
Python es como Perl en este aspecto. Parafraseando una famosa línea sobre privacidad del libro de Perl, la filosofía es que debes permanecer fuera de la sala porque no fuiste invitado, no porque esté defendido con una escopeta.
Para más información:
- Variables privadas Documentación de Python
- Funciones privadas Sumérgete en Python , por Mark Pilgrim
- ¿Por qué los métodos ''privados'' de Python no son en realidad privados? Pregunta de 70528
La convención es anteponer "_" a clases internas, funciones y variables.
Para abordar el tema de las convenciones de diseño, y como dijo Christopher, realmente no existe lo que se llama "privado" en Python. Esto puede sonar retorcido para alguien que proviene del fondo de C / C ++ (como yo hace un tiempo), pero eventualmente, probablemente te darás cuenta que seguir las convenciones es suficiente.
Ver algo que tenga un guión bajo al frente debería ser una sugerencia lo suficientemente buena como para no usarlo directamente. Si le preocupa la salida de help(MyClass)
(que es lo que todos miran al buscar cómo usar una clase), los atributos / clases subrayados no están incluidos allí, por lo que terminará teniendo su "público". "interfaz descrita.
Además, tener todo lo público tiene sus propias ventajas asombrosas, como por ejemplo, puedes probar prácticamente cualquier cosa desde fuera (lo que no puedes hacer con constructos privados C / C ++).
Un patrón que a veces uso es este:
Definir una clase:
class x(object):
def doThis(self):
...
def doThat(self):
...
Crea una instancia de la clase, sobrescribiendo el nombre de la clase:
x = x()
Defina los símbolos que exponen la funcionalidad:
doThis = x.doThis
doThat = x.doThat
Eliminar la instancia en sí:
del x
Ahora tiene un módulo que solo expone sus funciones públicas.
Use dos guiones bajos para prefijar los nombres de los identificadores "privados". Para las clases de un módulo, utilice un guion bajo inicial y no se importarán con "desde módulo import *".
class _MyInternalClass:
def __my_private_method:
pass
(En Python no existe el verdadero "privado". Por ejemplo, Python simplemente destruye automáticamente los nombres de los miembros de la clase con guiones bajos dobles para que sean __clssname_mymember
. De modo que si conoces el nombre mutilado puedes usar la entidad "privada" de todos modos, mira aquí. Y, por supuesto, puedes elegir importar manualmente las clases "internas" si lo deseas).
Use un único prefijo de subrayado:
class _Internal:
...
Esta es la convención oficial de Python para símbolos ''internos''; "from module import *" no importa objetos con guiones bajos.
Editar: referencia a la convención de subrayado único