Encapsulación en Python 3

imagen


Definición


El significado del término "encapsulación" es vago y difiere de una fuente a otra. En general, se acepta que la encapsulación es uno de los principios fundamentales de la POO, aunque algunos artículos científicos omiten completamente la encapsulación de la lista. Por ejemplo, John Mitchell en el libro "Conceptos en lenguajes de programación", al enumerar los conceptos principales en OOP, menciona solo la abstracción, un término que se considera cercano a la encapsulación por significado, pero sin embargo es más extenso y de nivel superior. Robert Martin, por otro lado, en su libro Pure Architecture, declara explícitamente que la encapsulación, la herencia y el polimorfismo se consideran la base de la POO.


La variedad de definiciones dadas al término "encapsulación" es difícil de llevar a un denominador común. En general, se pueden distinguir dos enfoques del significado de este término. La encapsulación puede considerarse como:


  • comunicación de datos con métodos que controlan estos datos;
  • Un conjunto de herramientas para controlar el acceso a datos o métodos que administran estos datos.

Encapsulación como conexión


Este tipo de interpretación del término "encapsulación" es muy fácil de explicar. En este caso, cualquier clase en la que haya al menos una variable y un método que lo controle demuestra claramente este principio.


#!/usr/bin/python3 class Phone: number = "111-11-11" def print_number(self): print( "Phone number is: ", self.number ) my_phone = Phone() my_phone.print_number() input( "Press Enter to exit" ) 

La clase Phone combina los datos en el número variable con el método print_number ()


Puede crear una clase que consista solo en métodos (y que no contenga variables), lo que puede ser conveniente en algunos lenguajes de programación. También es posible crear una clase que contenga solo datos, sin métodos, que, en muchos casos, deben evitarse. Ambas prácticas deben aplicarse cuando sea necesario, y su relación con la encapsulación "unificadora" es discutible.


Encapsulación como control de acceso


Explicar el concepto de restringir el acceso a datos o métodos requiere muchos más detalles. En primer lugar, en este contexto, el término "acceso" debe entenderse como la capacidad de ver y / o modificar los contenidos internos de una clase. Hay varios niveles de acceso proporcionados por la mayoría de los idiomas OOP. Resumiendo, podemos decir que los datos del objeto pueden ser:


  • public ( public ): los datos están disponibles para todos;
  • privado ( private ): los datos están disponibles solo para el objeto / clase al que pertenece.

La mayoría de los idiomas tienen grados de acceso adicionales que se encuentran entre estos límites. Por ejemplo, en C ++ y Python3 hay tres niveles de acceso: público, protegido y privado; C # agrega la palabra clave "interno" a la lista.


Vale la pena señalar que en la mayoría de los lenguajes de programación, el nivel de acceso a los datos se establece de forma predeterminada. Por ejemplo, en C ++, de manera predeterminada, el nivel de acceso a los datos en una clase se establece en privado: solo los miembros y amigos de la clase pueden acceder a sus datos. El nivel estándar de acceso a la estructura ( struct ) en C ++ es diferente: es público y los datos en dicha estructura pueden ser accesibles para cualquier persona. El nivel de acceso para las variables y métodos de clase en Python 3 depende completamente de la sintaxis.


Ejemplos


Encapsulación


Python 3 proporciona 3 niveles de acceso a datos:


  • public ( public , sin sintaxis especial, publicBanana );
  • protected ( protected , un guión bajo al comienzo del nombre, _protectedBanana );
  • privado ( private , dos guiones bajos al comienzo del nombre, __privateBanana ).

Por brevedad y simplicidad, solo dos niveles básicos (privado y público) se destacan en el ejemplo.


 #!/usr/bin/python3 class Phone: username = "Kate" # public variable __how_many_times_turned_on = 0 # private variable def call(self): # public method print( "Ring-ring!" ) def __turn_on(self): # private method self.__how_many_times_turned_on += 1 print( "Times was turned on: ", self.__how_many_times_turned_on ) my_phone = Phone() my_phone.call() print( "The username is ", my_phone.username ) # my_phone.turn_on() # my_phone.__turn_on() # print( “Turned on: “, my_phone.__how_many_times_turned_on) # print( “Turned on: “, my_phone.how_many_times_turned_on) # will produce an error input( "Press Enter to exit" ) 

Se puede obtener acceso a variables y métodos públicos desde el programa principal. Intentar recuperar datos privados o ejecutar un método privado dará como resultado un error.


Violación de encapsulación


El lenguaje en sí mismo proporciona al programador una herramienta de sintaxis que puede evitar la encapsulación. Todavía es posible leer y modificar variables privadas y llamar a funciones privadas.


 #!/usr/bin/python3 class Phone: username = "Kate" # public variable __serial_number = "11.22.33" # private variable __how_many_times_turned_on = 0 # private variable def call(self): # public method print( "Ring-ring!" ) def __turn_on(self): # private method self.__how_many_times_turned_on += 1 print( "Times was turned on: ", self.__how_many_times_turned_on ) my_phone = Phone() my_phone._Phone__turn_on() my_phone._Phone__serial_number = "44.55.66" print( "New serial number is ", my_phone._Phone__serial_number ) input( "Press Enter to exit" ) 

Algunas palabras sobre magia


Existen métodos, los llamados "métodos mágicos" o "métodos especiales", que permiten a las clases determinar su comportamiento con respecto a los operadores de lenguaje estándar. Las siguientes expresiones pueden servir como ejemplo de tales operadores de lenguaje:


  • x > y
  • x[ i ]

Python 3 admite muchos de estos métodos, se puede encontrar una lista completa en la página oficial de documentación del idioma. __init__ (inicializador) es el más utilizado y comienza cuando se crea un nuevo objeto de clase. El otro, __lt__ (comparación avanzada), define reglas para comparar dos objetos de una clase de usuario. Dichos métodos no entran en la categoría de "privado" o "público", ya que sirven para otros propósitos y están profundamente enraizados en la estructura interna del lenguaje.


 #!/usr/bin/python3 class Phone: def __init__(self, number): # magic method / inititalizer print( "The Phone object was created" ) self.number = number def __lt__(self, other): # magic method / rich comparison return self.number < other.number my_phone = Phone(20) other_phone = Phone(30) if my_phone < other_phone: print( "Two instances of custom class were compared" ) print( "'__lt__' was called implicitly" ) if my_phone.__lt__(other_phone): print( "Now, '__lt__' was used explicitly" ) input( "Press Enter to exit" ) 

Cualquier usuario puede invocar los métodos mágicos de la misma manera que cualquier método público en Python, pero están destinados a ser utilizados implícitamente en sus casos especiales. Un caso especial para el método __init__ es la inicialización de un nuevo objeto de clase. __lt__ se usa para comparar dos objetos.


Conclusión


Python3 no proporciona acceso limitado a ninguna variable de clase o método. Los datos que deben ocultarse pueden leerse y modificarse. En Python3, la encapsulación es más una convención, y el programador debe ocuparse de preservarla por su cuenta.


Fuentes


  1. John C. Mitchell, Conceptos en lenguajes de programación
  2. Robert C. Martin, Clean Architecture, A Craftsman's Guide to Software Structure and Design

Source: https://habr.com/ru/post/444338/


All Articles