¿Por qué no hay modificadores de acceso explícito en Python:

28

Si 'explícito es mejor que implícito', ¿por qué no hay modificadores de acceso explícito en Python: público, protegido, privado, etc.?

Sé que la idea es que el programador debe saber qué hacer a través de una pista: no es necesario usar 'fuerza bruta'. Pero la 'Encapsulación' o 'ocultamiento de información' de la OMI no es solo para mantener a las personas fuera, es una cuestión de organización y estructura: sus capas de desarrollo deben tener ámbitos y fronteras claramente definidas y delimitadas, al igual que los sistemas físicos.

¿Puede alguien ayudarme aquí con una explicación sólida de por qué las restricciones de acceso están implícitas en lugar de explícitas en Python, un lenguaje que de otro modo parece casi perfecto?

Editar: hasta ahora he visto 3 respuestas propuestas, y me di cuenta de que hay 2 partes en mi pregunta:

  1. ¿Por qué no hay palabras clave, por ejemplo

    private def myFunc(): 
        dostuff....
    

    en lugar de IMO, los subrayados feos y difíciles de escribir. Pero ese no es el punto importante.

  2. Más importante:

    ¿Por qué estos modificadores de acceso son solo 'recomendaciones' o sugerencias y no se aplican? ¿Será difícil cambiarlo más tarde? Es muy simple cambiar 'protegido' a 'público', y si tiene una cadena de herencia enrevesada que lo dificulta, tiene un diseño deficiente: su diseño debe ser refinado en lugar de depender de una función de lenguaje que lo haga fácil de escribir código mal estructurado

    Cuando se aplican los modificadores de acceso, su código se divide automáticamente en compartimentos: usted SABE que ciertos segmentos están fuera de alcance, por lo que no tiene que lidiar con ellos, excepto cuando sea necesario. Y, si su diseño no es bueno y se encuentra constantemente moviendo cosas dentro y fuera de diferentes ámbitos, el lenguaje puede ayudarlo a limpiar su acto.

Por mucho que ame a Python, encuentro que este segundo punto es una deficiencia grave. Y todavía tengo que ver una buena respuesta para esto.

Vector
fuente
posible duplicado de especificadores de acceso en Python: ... que se cerró por no ser constructivo.
Frank Shearar
2
@ Frank esta es una nueva pregunta de esa pregunta para intentar ser más constructivo. Seguí adelante y eliminé la pregunta original.
@ Mark Trapp: Ah, está bien. Gracias por la aclaración. No puedo ver cómo rescindir mi voto de cierre.
Frank Shearar
@Frank envejecerá solo.
Adam Lear
el problema private def whateveres que class x: def whatever(self): passes un atajo para class x: pass; x.whatever = lambda self: pass, así que básicamente, necesitaría un modificador privado para la asignación
keppla

Respuestas:

22

"Explícito es mejor que implícito" es solo una de las máximas en la filosofía de diseño de Python. "Simple es mejor que complejo" también está ahí. Y, aunque no está en el Zen de Python, "Todos estamos consintiendo adultos aquí" es otra.

Esa segunda regla es quizás la más importante aquí. Cuando diseño una clase, tengo una idea de cómo se va a usar. Pero no puedo predecir todos los usos posibles. Se puede ser que algún uso futuro de mi código requiere el acceso a las variables que he pensado como privado. ¿Por qué debería hacer que sea difícil, o incluso imposible, acceder a ellos si un futuro programador (o incluso un futuro yo) los necesita? Lo mejor que puede hacer es marcarlos con una advertencia, como señala Joonas, el prefijo de subrayado único es el estándar, que son internos y pueden cambiar; pero prohibir el acceso por completo parece innecesario.

Daniel Roseman
fuente
1
"Simple es mejor que complejo" y "Aquí todos aceptamos adultos" es la razón por la cual Smalltalk no tiene modificadores de acceso. Poner un método en la categoría "privada" es una pista que debes pensar tres veces antes de usarlo, y nada más.
Frank Shearar
@Frank: "Poner un método en la categoría" privada "es una pista que debes pensar tres veces antes de usarlo, y nada más" Para mí, simplemente significa que no tengo que preocuparme por eso cuando no estoy tratando con eso.
Vector del
8
Hay una buena razón por la cual prohibir el acceso a miembros privados: porque puede romper invariantes de clase. Si no puede escribir miembros privados, entonces no puede estar seguro de que su clase se comporta correctamente.
svick
77
"¿Por qué debería hacer que sea difícil, o incluso imposible, acceder a estos, si un futuro programador (o incluso un futuro yo) los necesita?" Porque uno de los principios básicos del diseño es la separación entre la interfaz (lo que proporciona un fragmento de código) y la implementación (cómo lo proporciona). La encapsulación sirve para reducir la complejidad del código al reducir las dependencias entre diferentes partes del código. Por lo tanto, público y privado se usan exactamente con el propósito de mantener el código más simple al permitir ver solo lo que se necesita.
Giorgio
3
No puedo diagree más. Los modificadores de acceso promueven dos de los conceptos probablemente mejor entendidos para reducir la complejidad en el software grande: encapsulación y separación de preocupaciones. No servir a ninguno de los dos simplemente significa que Python no es un buen lenguaje de programación orientada a objetos ni adecuado para construir software grande y no hay nada de malo en eso. Pero justificar la ausencia de tales características con argumentos típicos de aficionados como "¿Por qué agregar complejidad cuando no es necesario?" está mal
Daniel Shin
10

Sospecho que la razón principal de los modificadores de acceso que faltan es la simplicidad

Como usted dice, no se trata de mantener a las personas fuera, se trata de la organización, por lo que el punto principal de 'privado' es que envía un mensaje a los usuarios de su API 'por favor no escriba el código que depende de esto'.

Es trivial decir 'por convención, _x o __x no deberían usarse fuera de la clase', pero en el modelo de objetos dinámicos de Python, sería difícil incluso llegar a una notación.

class ActiveRow(object):
    def __init__(self, **kwargs):
        for name, value in kwargs.items():
            setattr(self, name, value)

¿Cómo notar la accesibilidad?

Supongo que esto fue una compensación. Si estrictamente no puede vivir con él, sugeriría ruby, que tiene un nivel similar de abstracción y dinámica, pero tiene un modelo de objeto, que permite la modificación del acceso.

keppla
fuente
8
Creo que esto es correcto, pero en mi opinión, es terrible. Para un lenguaje que usa elegancia y legibilidad como puntos de venta, escribir __método__ es bastante atroz y obtuso.
jiggy
2
esa no es la convención, __x__son 'mágicos' (es decir, métodos que se llaman para permitir la integración del lenguaje, como sobrecarga del operador, iterabilidad, etc.). La convención es _x.
keppla
66
Lo siento, todavía estoy entendiendo Python. Estoy tratando mucho de que me guste, pero cosas como esta me ponen un poco loco. Especialmente ahora que necesito recordar el significado de cuántos guiones bajos tiene un método. Para el punto de OP, parece que los modificadores explícitos serían más claros. La concisión es excelente, pero no puede superar la claridad. Gastas 10 veces más esfuerzo manteniendo el código que construyéndolo.
jiggy
2
Mi ejemplo no estaba destinado a mostrar diferentes recuentos de guiones bajos, el uso de __init__fue incidental. El ejemplo establece algunas propiedades del objeto, que no se conocen en tiempo de compilación, por lo que un modificador de acceso explícito no lo ayudaría.
keppla
55
@jiggy: "Estoy tratando de que me guste". Lo intenté durante 2 años y luego me di por vencido. :-( Parece ser un lenguaje de secuencias de comandos que fue pirateado para comportarse como un verdadero lenguaje OOP. No me puedo imaginar escribir una aplicación grande y compleja en Python que esté bien diseñada y sea legible. Como dijiste: 'Pasas 10 veces más esfuerzo mantener el código que construirlo ". Los conceptos simples de OOP y de tipo seguro requieren trucos y soluciones alternativas.
Vector
8

La convención de Python es usar un prefijo de subrayado para miembros protegidos / privados.

Esta convención, cuando se sigue, es efectivamente igual que los modificadores de acceso, excepto 1) verá directamente desde el nombre del miembro si es público o no, y 2) puede romper la "encapsulación" si realmente lo desea (esto puede ser justificable en, por ejemplo, pruebas; en algunos otros idiomas tendría que usar la reflexión == más código)

En última instancia, es una cuestión de gustos, pero si puede hacer lo mismo (con un poco más de flexibilidad) sin palabras clave especiales, el idioma será más pequeño y el código será más conciso, lo que generalmente es algo bueno.

Joonas Pulakka
fuente
2
"Si puede hacer lo mismo (con un poco más de flexibilidad) sin palabras clave especiales, el idioma será más pequeño y el código será más conciso" En mi opinión, esto generalmente no es cierto. (Incluso si puede ser cierto con el caso especial de modificadores de acceso)
BenjaminB