Encapsulation dans Python 3

image


Définition


Le sens du terme «encapsulation» est vague et diffère d'une source à l'autre. Il est généralement admis que l'encapsulation est l'un des principes fondamentaux de la POO, bien que certains articles scientifiques omettent complètement l'encapsulation de la liste. Par exemple, John Mitchell dans le livre «Concepts in Programming Languages», lors de l'énumération des principaux concepts en POO, ne mentionne que l'abstraction - un terme qui est considéré comme proche de l'encapsulation par le sens, mais toujours plus étendu et de niveau supérieur. D'autre part, Robert Martin, dans son livre Pure Architecture, déclare explicitement que l'encapsulation, l'héritage et le polymorphisme sont considérés comme le fondement de la POO.


La variété des définitions données au terme «encapsulation» est difficile à apporter à un dénominateur commun. En général, deux approches de la signification de ce terme peuvent être distinguées. L'encapsulation peut être considérée comme:


  • communication des données avec des méthodes qui contrôlent ces données;
  • Un ensemble d'outils pour contrôler l'accès aux données ou aux méthodes qui gèrent ces données.

Encapsulation comme connexion


Ce type d'interprétation du terme «encapsulation» est très facile à expliquer. Dans ce cas, toute classe dans laquelle il existe au moins une variable et une méthode qui la contrôle démontre clairement ce principe.


#!/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 classe Phone combine les données du nombre variable avec la méthode print_number ()


Vous pouvez créer une classe composée uniquement de méthodes (et ne contenant pas de variables), ce qui peut être pratique dans certains langages de programmation. Il est également possible de créer une classe contenant uniquement des données, sans méthodes, ce qui, dans de nombreux cas, doit être évité. Les deux pratiques devraient être appliquées lorsque cela est nécessaire, et leur relation avec l'encapsulation «unificatrice» est discutable.


Encapsulation comme contrôle d'accès


Expliquer le concept de restreindre l'accès aux données ou aux méthodes nécessite beaucoup plus de détails. Tout d'abord, dans ce contexte, le terme «accès» doit être compris comme la capacité de voir et / ou de modifier le contenu interne d'une classe. Il existe plusieurs niveaux d'accès fournis par la plupart des langues POO. En résumé, on peut dire que les données de l'objet peuvent être:


  • public ( public ) - les données sont accessibles à tous;
  • privé ( private ) - les données ne sont disponibles que pour l'objet / la classe auquel elles appartiennent.

La plupart des langues ont des degrés d'accès supplémentaires qui se situent entre ces frontières. Par exemple, en C ++ et Python3, il existe trois niveaux d'accès: public, protégé et privé; C # ajoute le mot-clé «interne» à la liste.


Il convient de noter que dans la plupart des langages de programmation, le niveau d'accès à toutes les données est défini par défaut. Par exemple, en C ++, par défaut, le niveau d'accès aux données dans une classe est défini sur privé - seuls les membres et amis de la classe peuvent accéder à ses données. Le niveau standard d'accès à la structure ( struct ) en C ++ est différent - il est public, et les données d'une telle structure peuvent être accessibles à tous. Le niveau d'accès pour les variables et méthodes de classe dans Python 3 dépend entièrement de la syntaxe.


Des exemples


Encapsulation


Python 3 offre 3 niveaux d'accès aux données:


  • public ( public , pas de syntaxe spéciale, publicBanana );
  • protected ( protected , un trait de soulignement au début du nom, _protectedBanana );
  • privé ( private , deux soulignements au début du nom, __privateBanana ).

Par souci de concision et de simplicité, seuls deux niveaux de base (privé et public) sont mis en évidence dans l'exemple.


 #!/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" ) 

L'accès aux variables et méthodes publiques peut être obtenu à partir du programme principal. Tenter de récupérer des données privées ou d'exécuter une méthode privée entraînera une erreur.


Violation d'encapsulation


Le langage lui-même fournit au programmeur un outil de syntaxe qui peut contourner l'encapsulation. La lecture et la modification de variables privées et l'appel de fonctions privées sont toujours possibles.


 #!/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" ) 

Quelques mots sur la magie


Il existe des méthodes, dites «méthodes magiques» ou «méthodes spéciales», qui permettent aux classes de déterminer leur comportement par rapport aux opérateurs de langage standard. Les expressions suivantes peuvent servir d'exemple de tels opérateurs de langage:


  • x > y
  • x[ i ]

Python 3 prend en charge bon nombre de ces méthodes, une liste complète peut être trouvée sur la page de documentation en langue officielle. __init__ (initialiseur) est le plus utilisé d'entre eux et démarre lorsqu'un nouvel objet de classe est créé. L'autre, __lt__ (comparaison avancée), définit des règles pour comparer deux objets d'une classe d'utilisateurs. Ces méthodes n'entrent pas dans la catégorie «privé» ou «public», car elles servent à d'autres fins et sont profondément enracinées dans la structure interne de la langue.


 #!/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" ) 

Les méthodes magiques peuvent être appelées par n'importe quel utilisateur de la même manière que n'importe quelle méthode publique en Python, mais elles sont destinées à être implicitement utilisées dans leurs cas particuliers. Un cas particulier pour la méthode __init__ est l'initialisation d'un nouvel objet de classe. __lt__ est utilisé pour comparer deux objets.


Conclusion


Python3 ne fournit un accès limité à aucune variable ou méthode de classe. Les données qui doivent être cachées peuvent en effet être lues et modifiées. En Python3, l'encapsulation est plus une convention, et le programmeur doit prendre soin de la conserver par lui-même.


Les sources


  1. John C. Mitchell, Concepts dans les langages de programmation
  2. Robert C. Martin, Clean Architecture, A Craftsman's Guide to Software Structure and Design

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


All Articles