Vengo del mundo Java y leo los patrones, recetas y modismos de Python 3 de Bruce Eckels .
Mientras lee sobre las clases, continúa diciendo que en Python no es necesario declarar variables de instancia. Solo los usas en el constructor, y boom, están ahí.
Así por ejemplo:
class Simple:
def __init__(self, s):
print("inside the simple constructor")
self.s = s
def show(self):
print(self.s)
def showMsg(self, msg):
print(msg + ':', self.show())
Si eso es cierto, entonces cualquier objeto de la clase Simple
puede simplemente cambiar el valor de la variable s
fuera de la clase.
Por ejemplo:
if __name__ == "__main__":
x = Simple("constructor argument")
x.s = "test15" # this changes the value
x.show()
x.showMsg("A message")
En Java, se nos ha enseñado sobre variables públicas / privadas / protegidas. Esas palabras clave tienen sentido porque a veces desea variables en una clase a las que nadie fuera de la clase tiene acceso.
¿Por qué no es necesario en Python?
Es cultural. En Python, no escribe en la instancia de otras clases o en las variables de clase. En Java, nada le impide hacer lo mismo si realmente lo desea; después de todo, siempre puede editar el código fuente de la clase para lograr el mismo efecto. Python abandona esa pretensión de seguridad y anima a los programadores a ser responsables. En la práctica, esto funciona muy bien.
Si desea emular variables privadas por alguna razón, siempre puede usar el __
prefijo de PEP 8 . Python modifica los nombres de las variables como __foo
para que no sean fácilmente visibles para el código fuera de la clase que las contiene (aunque puede evitarlo si está lo suficientemente determinado, al igual que puede sortear las protecciones de Java si trabaja en ello ).
Según la misma convención, el _
prefijo significa mantenerse alejado incluso si técnicamente no se le impide hacerlo . No juegas con las variables de otra clase que se parecen a __foo
o _bar
.
Las variables privadas en Python son más o menos un truco: el intérprete cambia el nombre de la variable intencionalmente.
class A:
def __init__(self):
self.__var = 123
def printVar(self):
print self.__var
Ahora, si intenta acceder __var
fuera de la definición de clase, fallará:
>>>x = A()
>>>x.__var # this will return error: "A has no attribute __var"
>>>x.printVar() # this gives back 123
Pero puedes salirte con la tuya fácilmente:
>>>x.__dict__ # this will show everything that is contained in object x
# which in this case is something like {'_A__var' : 123}
>>>x._A__var = 456 # you now know the masked name of private variables
>>>x.printVar() # this gives back 456
Probablemente sepa que los métodos en OOP se invocan así:, x.printVar() => A.printVar(x)
si A.printVar()
puede acceder a algún campo x
, también se puede acceder a este campo desde el exterior A.printVar()
... después de todo, las funciones se crean para su reutilización, no hay ningún poder especial otorgado a las declaraciones dentro.
El juego es diferente cuando hay un compilador involucrado (la privacidad es un concepto a nivel de compilador ). Conoce la definición de clase con modificadores de control de acceso, por lo que puede generar errores si no se siguen las reglas en el momento de la compilación.
Como se menciona correctamente en muchos de los comentarios anteriores, no olvidemos el objetivo principal de los modificadores de acceso: ayudar a los usuarios del código a comprender qué se supone que debe cambiar y qué no. Cuando ve un campo privado, no se mete con él. Por lo tanto, es principalmente azúcar sintáctico que se logra fácilmente en Python mediante _ y __.
Hay una variación de variables privadas en la convención de subrayado.
In [5]: class Test(object):
...: def __private_method(self):
...: return "Boo"
...: def public_method(self):
...: return self.__private_method()
...:
In [6]: x = Test()
In [7]: x.public_method()
Out[7]: 'Boo'
In [8]: x.__private_method()
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-8-fa17ce05d8bc> in <module>()
----> 1 x.__private_method()
AttributeError: 'Test' object has no attribute '__private_method'
Hay algunas diferencias sutiles, pero en aras de la pureza ideológica del patrón de programación, es lo suficientemente bueno.
Hay ejemplos de decoradores @private que implementan más de cerca el concepto, pero YMMV. Podría decirse que también se podría escribir una definición de clase que use meta
Como se mencionó anteriormente, puede indicar que una variable o método es privado colocándolo como prefijo con un guión bajo. Si cree que esto no es suficiente, siempre puede usar el property
decorador. He aquí un ejemplo:
class Foo:
def __init__(self, bar):
self._bar = bar
@property
def bar(self):
"""Getter for '_bar'."""
return self._bar
De esta manera, alguien o algo que hace referencia en bar
realidad hace referencia al valor de retorno de la bar
función en lugar de a la variable en sí, y por lo tanto se puede acceder a ella pero no cambiar. Sin embargo, si alguien realmente quisiera, simplemente podría usarlo _bar
y asignarle un nuevo valor. No existe una forma segura de evitar que alguien acceda a las variables y métodos que desea ocultar, como se ha dicho repetidamente. Sin embargo, usar property
es el mensaje más claro que puede enviar de que una variable no debe editarse. property
también se puede usar para rutas de acceso de captador / definidor / eliminador más complejas, como se explica aquí:https://docs.python.org/3/library/functions.html#property
"En Java, se nos ha enseñado acerca de las variables públicas / privadas / protegidas"
"¿Por qué no es necesario en Python?"
Por la misma razón, no es necesario en Java.
Eres libre de usar o no usar private
y protected
.
Como programador de Python y Java, he encontrado que private
y protected
son muy, muy importantes conceptos de diseño. Sin embargo, como cuestión práctica, en decenas de miles de líneas de Java y Python, nunca he hecho acostumbrado private
o protected
.
¿Por qué no?
Aquí está mi pregunta "¿protegido de quién?"
¿Otros programadores de mi equipo? Tienen la fuente. ¿Qué significa protegido cuando pueden cambiarlo?
¿Otros programadores en otros equipos? Trabajan para la misma empresa. Pueden, con una llamada telefónica, obtener la fuente.
¿Clientela? Es programación de trabajo por contrato (generalmente). Los clientes (generalmente) poseen el código.
Entonces, ¿de quién, precisamente, lo estoy protegiendo?
Python tiene soporte limitado para identificadores privados, a través de una función que antepone automáticamente el nombre de la clase a cualquier identificador que comience con dos guiones bajos. Esto es transparente para el programador, en su mayor parte, pero el efecto neto es que cualquier variable nombrada de esta manera puede usarse como variable privada.
Consulte aquí para obtener más información al respecto.
En general, la implementación de Python de la orientación a objetos es un poco primitiva en comparación con otros lenguajes. Pero disfruto esto, de hecho. Es una implementación muy simple desde el punto de vista conceptual y encaja bien con el estilo dinámico del lenguaje.
Python no tiene variables privadas como C ++ o Java. También puede acceder a cualquier variable miembro en cualquier momento si lo desea. Sin embargo, no necesita variables privadas en Python, porque en Python no está mal exponer las variables miembro de sus clases. Si tiene la necesidad de encapsular una variable miembro, puede hacerlo usando "@property" más adelante sin romper el código de cliente existente.
En Python, el guión bajo "_" se usa para indicar que un método o variable no se considera parte de la API pública de una clase y que esta parte de la API podría cambiar entre diferentes versiones. Puede usar estos métodos / variables, pero su código podría romperse si usa una versión más nueva de esta clase.
El doble subrayado "__" no significa una "variable privada". Se usa para definir variables que son de "clase local" y que no pueden ser fácilmente reemplazadas por subclases. Destroza el nombre de las variables.
Por ejemplo:
class A(object):
def __init__(self):
self.__foobar = None # will be automatically mangled to self._A__foobar
class B(A):
def __init__(self):
self.__foobar = 1 # will be automatically mangled to self._B__foobar
self .__ el nombre de foobar se convierte automáticamente en self._A__foobar en la clase A. En la clase B se convierte en self._B__foobar. Entonces, cada subclase puede definir su propia variable __foobar sin anular su (s) variable (s) principal (s). Pero nada le impide acceder a las variables que comienzan con guiones bajos dobles. Sin embargo, la alteración de nombres le impide llamar a estas variables / métodos de manera incidental.
Recomiendo encarecidamente ver a Raymond Hettingers hablar sobre el "kit de herramientas de desarrollo de clases Pythons" de Pycon 2013 (debería estar disponible en Youtube), que da un buen ejemplo de por qué y cómo se debe usar @property y "__" - variables de instancia.
Si ha expuesto variables públicas y tiene la necesidad de encapsularlas, puede usar @property. Por lo tanto, puede comenzar con la solución más simple posible. Puede dejar públicas las variables de miembro a menos que tenga una razón concreta para no hacerlo. Aquí hay un ejemplo:
class Distance:
def __init__(self, meter):
self.meter = meter
d = Distance(1.0)
print(d.meter)
# prints 1.0
class Distance:
def __init__(self, meter):
# Customer request: Distances must be stored in millimeters.
# Public available internals must be changed.
# This would break client code in C++.
# This is why you never expose public variables in C++ or Java.
# However, this is python.
self.millimeter = meter * 1000
# In python we have @property to the rescue.
@property
def meter(self):
return self.millimeter *0.001
@meter.setter
def meter(self, value):
self.millimeter = meter * 1000
d = Distance(1.0)
print(d.meter)
# prints 1.0
La única vez que uso variables privadas es cuando necesito hacer otras cosas al escribir o leer de la variable y, como tal, necesito forzar el uso de un setter y / o getter.
De nuevo, esto va a la cultura, como ya se dijo. He estado trabajando en proyectos en los que leer y escribir variables de otras clases era gratuito para todos. Cuando una implementación quedó en desuso, tomó mucho más tiempo identificar todas las rutas de código que usaban esa función. Cuando se forzó el uso de establecedores y captadores, se podría escribir fácilmente una declaración de depuración para identificar que se había llamado al método obsoleto y la ruta del código que lo llama.
Cuando se encuentra en un proyecto en el que cualquiera puede escribir una extensión, notificar a los usuarios sobre los métodos obsoletos que desaparecerán en algunas versiones, por lo tanto, es vital para mantener la rotura del módulo al mínimo en las actualizaciones.
Entonces mi respuesta es; si usted y sus colegas mantienen un conjunto de códigos simple, no siempre es necesario proteger las variables de clase. Si está escribiendo un sistema extensible, entonces se vuelve imperativo cuando se realizan cambios en el núcleo que deben ser detectados por todas las extensiones que usan el código.
Lo siento chicos por "resucitar" el hilo, pero espero que esto ayude a alguien:
En Python3, si solo desea "encapsular" los atributos de la clase, como en Java, puede hacer lo mismo como esto:
class Simple:
def __init__(self, str):
print("inside the simple constructor")
self.__s = str
def show(self):
print(self.__s)
def showMsg(self, msg):
print(msg + ':', self.show())
Para crear una instancia de esto, haga lo siguiente:
ss = Simple("lol")
ss.show()
Tenga en cuenta que: print(ss.__s)
arrojará un error.
En la práctica, Python3 ofuscará el nombre del atributo global. Convirtiendo esto como un atributo "privado", como en Java. El nombre del atributo sigue siendo global, pero de forma inaccesible, como un atributo privado en otros idiomas.
Pero no le tengas miedo. No importa. También hace el trabajo. ;)
Los conceptos privados y protegidos son muy importantes. Pero python: solo una herramienta para la creación de prototipos y el desarrollo rápido con recursos restringidos disponibles para el desarrollo, es por eso que algunos de los niveles de protección no son tan estrictos en Python. Puede usar "__" en el miembro de la clase, funciona correctamente, pero no se ve lo suficientemente bien; cada acceso a dicho campo contiene estos caracteres.
Además, puede notar que el concepto de Python OOP no es perfecto, pequeño o ruby mucho más cercano al concepto puro de OOP. Incluso C # o Java están más cerca.
Python es una muy buena herramienta. Pero es un lenguaje OOP simplificado. Simplificado sintáctica y conceptualmente. El objetivo principal de la existencia de Python es brindar a los desarrolladores la posibilidad de escribir código fácil de leer con un alto nivel de abstracción de una manera muy rápida.
Acerca de las fuentes (para cambiar los derechos de acceso y así evitar la encapsulación del lenguaje como java o C ++): no siempre tiene las fuentes e INCLUSO si las tiene, las fuentes son administradas por un sistema que solo permite a ciertos programadores acceder a un fuente (en un contexto profesional). A menudo, todo programador es responsable de determinadas clases y, por tanto, sabe lo que puede y lo que no puede hacer. El administrador de fuentes también bloquea las fuentes que se están modificando y, por supuesto, administra los derechos de acceso de los programadores.
Por eso confío más en el software que en el ser humano, por experiencia. Así que la convención es buena, pero las protecciones MÚLTIPLES son mejores, como la gestión de acceso (variable privada real) + la gestión de fuentes.
La estrella de HGTV, Christina Hall, revela que le diagnosticaron envenenamiento por mercurio y plomo, probablemente debido a su trabajo como manipuladora de casas.
Recientemente salió a la luz un informe policial que acusa a la estrella de 'Love Is Blind', Brennon, de violencia doméstica. Ahora, Brennon ha respondido a los reclamos.
Conozca cómo Wynonna Judd se dio cuenta de que ahora es la matriarca de la familia mientras organizaba la primera celebración de Acción de Gracias desde que murió su madre, Naomi Judd.
Descubra por qué un destacado experto en lenguaje corporal cree que es fácil trazar "tales paralelismos" entre la princesa Kate Middleton y la princesa Diana.
Los inodoros arrojan columnas de aerosol invisibles con cada descarga. ¿Como sabemos? La prueba fue capturada por láseres de alta potencia.
Air travel is far more than getting from point A to point B safely. How much do you know about the million little details that go into flying on airplanes?
The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!
¿Sigue siendo efectivo ese lote de repelente de insectos que te quedó del verano pasado? Si es así, ¿por cuánto tiempo?
Anteriormente, Kotaku informó que un hotel Godzilla se estaba abriendo en Tokio este abril. Junto al hotel, estaba programada la aparición de una enorme cabeza de 'Zilla, pero todo lo que hemos visto fueron imágenes conceptuales computarizadas.
Foto: Getty Desde que lanzó The Boring Company hace un año, Elon Musk ha mencionado varios sitios de construcción posibles para el negocio de perforación de túneles y ha descartado una vaga referencia a una aprobación gubernamental "verbal" para un túnel Hyperloop que conecta la ciudad de Nueva York y Washington. , CC. Pero ahora sabemos que al menos un alcalde quiere que Musk perfore un agujero debajo de su ciudad.
Tapas elásticas de silicona de Tomorrow's Kitchen, paquete de 12 | $14 | Amazonas | Código promocional 20OFFKINJALids son básicamente los calcetines de la cocina; siempre perdiéndose, dejando contenedores huérfanos que nunca podrán volver a cerrarse. Pero, ¿y si sus tapas pudieran estirarse y adaptarse a todos los recipientes, ollas, sartenes e incluso frutas en rodajas grandes que sobran? Nunca más tendrás que preocuparte por perder esa tapa tan específica.
Hemos pirateado algunas ciudades industriales en esta columna, como Los Ángeles y Las Vegas. Ahora es el momento de una ciudad militar-industrial-compleja.
El equipo está a la espera de las medallas que ganó en los Juegos Olímpicos de Invierno de 2022 en Beijing, ya que se está resolviendo un caso de dopaje que involucra a la patinadora artística rusa Kamila Valieva.
Miles de compradores de Amazon recomiendan la funda de almohada de seda Mulberry, y está a la venta en este momento. La funda de almohada de seda viene en varios colores y ayuda a mantener el cabello suave y la piel clara. Compre las fundas de almohada de seda mientras tienen hasta un 46 por ciento de descuento en Amazon
El jueves se presentó una denuncia de delito menor amenazante agravado contra Joe Mixon.
El Departamento de Policía de Lafayette comenzó a investigar a un profesor de la Universidad de Purdue en diciembre después de recibir varias denuncias de un "hombre sospechoso que se acercaba a una mujer".
Al igual que el mundo que nos rodea, el lenguaje siempre está cambiando. Mientras que en eras anteriores los cambios en el idioma ocurrían durante años o incluso décadas, ahora pueden ocurrir en cuestión de días o incluso horas.
Estoy de vuelta por primera vez en seis años. No puedo decirte cuánto tiempo he estado esperando esto.
“And a river went out of Eden to water the garden, and from thence it was parted and became into four heads” Genesis 2:10. ? The heart is located in the middle of the thoracic cavity, pointing eastward.
Creo, un poco tarde en la vida, en dar oportunidades a la gente. Generosamente.