Python est connu pour sa simplicité et sa lisibilité, mais lorsqu'il s'agit de programmation orientée objet (POO), il existe des mécanismes moins discutés qui sont cruciaux pour écrire du code robuste. L’un de ces mécanismes est la modification des noms. Cet article vous expliquera ce qu'est la modification de noms, pourquoi Python l'utilise et comment il peut aider à prévenir les collisions de noms dans des hiérarchies de classes complexes.
Python permet aux méthodes des classes d'être remplacées par des sous-classes. Cependant, cela peut parfois conduire à des conflits de noms lorsqu'une sous-classe remplace involontairement les attributs ou les méthodes de la classe parent. La modification des noms est un mécanisme utilisé par Python pour éviter ces conflits, en particulier pour les attributs censés être privés.
La modification des noms en Python est une fonctionnalité dans laquelle l'interpréteur modifie les noms des propriétés de classe privée afin de minimiser le risque qu'elles soient consultées et remplacées par erreur. Cela fournit un certain niveau de confidentialité dans les attributs de classe, bien qu'il ne soit pas strictement appliqué. Cependant, il ne s’agit pas d’une application stricte.
En Python, tout identifiant avec deux traits de soulignement en tête (__) et pas plus d'un trait de soulignement à la fin subira une modification de nom. L'interpréteur transforme le nom en le préfixant avec le nom de la classe.
Afin d'éviter les conflits de noms, en particulier dans le cas où les sous-classes peuvent avoir leurs propres variables pouvant remplacer les variables de la classe parent, Python implémente la modification des noms. La modification des noms résout ce problème.
from datetime import datetime, timedelta from time import time, sleep class Machine: def __init__(self, id): self.id = id self._started = time() def uptime(self): return time() - self._started class PetrolMachine(Machine): def __init__(self, id): super().__init__(id) self._started = datetime.now() def cost(self): duration = datetime.now() - self._started return duration/timedelta(seconds=60) *0.02 worked = PetrolMachine('12345') sleep(0.123) print(f"uptime : {worked.uptime():.2f}")
Dans cet exemple, la classe Machine stocke un identifiant et enregistre l'heure de début à l'aide de la fonction time() de Python. Lorsque vous demandez une disponibilité, il calcule la différence entre l'heure actuelle et l'heure de début, qui est stockée sous forme de nombre à virgule flottante. La sous-classe PetrolMachine, cependant, stocke l'heure de début en utilisant datetime.now(). Lorsque nous essayons de calculer la disponibilité, le programme génère une erreur car il s'attend à ce que start_time soit un nombre à virgule flottante, mais il s'agit désormais d'un objet datetime. Ce conflit de noms peut survenir lorsque les attributs de sous-classe remplacent involontairement les attributs de la classe parent. La modification des noms permet d'éviter ce problème.
Alors, comment la modification des noms aide-t-elle à résoudre ce problème ? Lorsqu'un attribut de classe est préfixé par deux traits de soulignement, Python modifie le nom en interne pour inclure le nom de la classe comme préfixe. Voici comment modifier la classe Machine pour éviter les conflits de noms en utilisant la modification de noms :
Nous pouvons résoudre l'erreur en appliquant une modification de nom à l'attribut __started dans la classe Machine, comme indiqué ci-dessous :
from datetime import datetime, timedelta from time import time, sleep class Machine: def __init__(self, id): self.id = id self.__started = time() def uptime(self): return time() - self.__started class PetrolMachine(Machine): def __init__(self, id): super().__init__(id) self._started = datetime.now() def cost(self): duration = datetime.now() - self._started return duration/timedelta(seconds=60) *0.02 worked = PetrolMachine('12345') sleep(0.123) print(f"uptime : {worked.uptime():.2f}")
Une façon simple d'exprimer la modification du nom est présentée ci-dessous. J'ai une classe ClassA, qui a une variable_privée, dont le nom est mutilé.
class MyClass: def __init__(self): self.__private_var = "I am private" def get_private_var(self): return self.__private_var my_object = MyClass() print(my_object.get_private_var()) # This works print(my_object.__private_var)
Le deuxième print() déclenchera une AttributeError car la variable __private_var a été modifiée en termes de nom. En interne, Python a changé le nom en _MyClass__private_var, ce qui rend plus difficile l'accès depuis l'extérieur de la classe.
Bien que la modification du nom de Python soit conçue pour empêcher tout accès accidentel, elle n'impose pas une confidentialité stricte. Vous pouvez toujours accéder à l'attribut mangled en utilisant le nom complet mangled, bien que cela soit déconseillé. Voici comment cela fonctionne : mon_objet._MaClass__private_var
print(my_object._MyClass__private_var)
Je vais l'expliquer à travers un exemple simple
class MyClass: def __init__(self): self._protected_var = "I'm protected" self.__private_var__ = "I'm not mangled"
En Python, un trait de soulignement unique (par exemple, _protected_var) indique que l'attribut est "protégé" et ne doit pas être accessible directement depuis l'extérieur de la classe. Cependant, Python n'applique pas cela. En revanche, les noms avec deux traits de soulignement en tête (par exemple, __private_var) sont modifiés pour éviter tout remplacement accidentel. Il est important de noter que les noms avec des traits de soulignement doubles des deux côtés (par exemple, __special__) ne sont pas modifiés et sont réservés à des cas d'utilisation spéciaux tels que les méthodes magiques.
_ Malgré ces limitations, la modification des noms reste un outil utile dans la boîte à outils POO de Python. Bien qu’il ne s’agisse pas d’une application stricte de la confidentialité, cela permet d’éviter les conflits de noms et le remplacement accidentel d’attributs. Comprendre la modification des noms vous permettra d'écrire un code plus robuste et plus maintenable, en particulier lorsque vous travaillez avec des hiérarchies de classes complexes. Essayez-le dans vos projets et partagez vos expériences ou questions dans les commentaires ci-dessous !_
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!