CodeGym /Cours Java /Python SELF FR /Méthodes et champs spéciaux

Méthodes et champs spéciaux

Python SELF FR
Niveau 15 , Leçon 5
Disponible

5.1 Niveaux d'accès

Tu as probablement remarqué le nom étrange du constructeur __init__? À l'avenir, tu rencontreras cela assez souvent.

En Python, il existe différents niveaux d'accès aux attributs et méthodes de classes qui aident à contrôler la visibilité et la protection des données. Les principaux mécanismes de gestion de l'accès incluent l'utilisation d'un ou deux soulignements (_ et __) devant le nom de l'attribut ou de la méthode.

Utilisation des conventions

Un seul soulignement _ est utilisé pour les attributs et méthodes qui ne doivent pas être utilisés en dehors de la classe ou du module. Ce n'est pas interdit, mais c'est une convention à suivre pour une meilleure lisibilité et maintenance du code.

Deux soulignements __ sont utilisés pour les attributs et méthodes qui doivent être vraiment privés et protégés contre l'accès accidentel ou intentionnel de l'extérieur. Le mécanisme de name mangling les rend moins accessibles, mais toujours accessibles à travers des noms spéciaux.

Champs et méthodes publics (public)

Les attributs et méthodes publics sont accessibles de n'importe où dans le code. En Python, par défaut, tous les attributs et méthodes sont publics si leurs noms ne commencent pas par un soulignement.


class MyClass:
    def __init__(self):
        self.public_attribute = "I am public"
        
    def public_method(self):
        return "This is a public method"
        

obj = MyClass()
print(obj.public_attribute)  # Disponible
print(obj.public_method())  # Disponible

Grâce aux niveaux d'accès en Python, l'encapsulation est mise en œuvre, notamment à travers les champs et méthodes non publics.

5.2 Champs et méthodes non publics

Champs et méthodes protégés (protected)

Les attributs et méthodes protégés sont désignés par un seul soulignement _ devant le nom et sont destinés à une utilisation interne dans la classe et ses sous-classes. C'est une convention qui indique aux programmeurs que les données ne sont pas destinées à être utilisées en dehors de la classe.


class MyClass:
    def __init__(self):
        self._protected_attribute = "I am protected"
        
    def _protected_method(self):
        return "This is a protected method"
        

obj = MyClass()
print(obj._protected_attribute)  # Disponible, mais déconseillé
print(obj._protected_method())  # Disponible, mais déconseillé

Champs et méthodes privés (private)

En Python, les attributs et méthodes privés sont désignés par deux soulignements __ devant le nom. Ces attributs et méthodes sont destinés à être utilisés exclusivement à l'intérieur de la classe, et leur principal objectif est de cacher l'implémentation interne et de protéger les données contre les modifications accidentelles ou l'utilisation de l'extérieur.

Pour empêcher l'accès direct à ces attributs et méthodes depuis un code externe, Python applique un mécanisme spécial connu sous le nom de name mangling (déformation du nom). Ce mécanisme modifie automatiquement les noms des attributs privés en ajoutant un préfixe composé du nom de la classe. Ainsi, l'attribut privé __private_attribute dans la classe MyClass sera transformé en un nom interne _MyClass__private_attribute.

Cela permet de protéger les données contre un accès involontaire, tout en conservant la possibilité de les manipuler à l'intérieur de la classe. Cependant, il est important de se rappeler que le mécanisme de "name mangling" n'est pas une protection absolue — un programmeur expérimenté peut accéder à ces données en utilisant le nom modifié.

Voyons comment cela fonctionne en pratique:


class MyClass:
    def __init__(self):
        self.__private_attribute = "I am private"
        
    def __private_method(self):
        return "This is a private method"
        
    def access_private_method(self):
        return self.__private_method()
         

obj = MyClass()
# print(obj.__private_attribute)  # Erreur, inaccessible directement
# print(obj.__private_method())  # Erreur, inaccessible directement
print(obj.access_private_method())  # Accessible via la méthode publique de la classe

Comme montré dans l'exemple, un accès direct aux attributs ou méthodes privés génère une erreur. Mais Python conserve la possibilité d'y accéder par le biais du nom modifié. Par exemple, tu peux accéder à l'attribut privé en utilisant le nom "déformé", comme illustré ci-dessous:


class MyClass:
    def __init__(self):
        self.__private_attribute = "I am private"
   
obj = MyClass()
print(obj._MyClass__private_attribute)  # Affiche : I am private

Bien qu'un accès via le nom "déformé" soit possible, il est préférable de l'éviter, car cela viole les principes de l'encapsulation et peut mener à une instabilité du code.

Pour voir comment Python modifie les noms des attributs, tu peux utiliser la fonction intégrée dir(), qui affiche tous les attributs et méthodes d'un objet:


class MyClass:
    def __init__(self):
        self.__private_attribute = "I am private"
   
obj = MyClass()
print(dir(obj))  # Affiche tous les attributs et méthodes de l'objet, y compris les noms "déformés"

En utilisant la fonction dir(), tu verras la liste de tous les attributs et méthodes de l'objet, incluant _MyClass__private_attribute, confirmant le mécanisme de "name mangling".

5.3 Appel automatique des méthodes

Il y avait un aspect intéressant en travaillant avec les constructeurs que tu as peut-être remarqué. La méthode __init__ était appelée automatiquement.

En fait, il y a pas mal de situations comme celle-ci et des méthodes pour ces cas. Des exemples:

Méthode __str__

Si ton objet a une méthode __str__, elle sera appelée automatiquement lorsque tu essaies de convertir ton objet en chaîne, par exemple, en utilisant les fonctions print() et str().


class Cat:
    def __init__(self, name, age):
        self.name = name
        self.age = age
            
    def __str__(self):
        return f"{self.name} is {self.age} years old"
            

cat = Cat("Barsik", 5)
print(cat)  # Affiche : Barsik is 5 years old

Méthode __len__

Et si ton objet a une méthode __len__, elle sera appelée automatiquement lorsque tu essaies de déterminer la « longueur » de ton objet — utilisée par la fonction len(). Exemple:


class MyList:
    def __init__(self, items):
        self.items = items
        
    def __len__(self):
        return len(self.items)
        
        
my_list = MyList([1, 2, 3])
print(len(my_list))  # Affiche : 3

Il y aura encore beaucoup de ces « méthodes spéciales » dans ta vie, mais travailler avec elles est un vrai plaisir. Alors prépare-toi :)

Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION