Maison  >  Article  >  développement back-end  >  Explorer la manipulation de noms en Python : qu'est-ce que c'est et comment cela fonctionne

Explorer la manipulation de noms en Python : qu'est-ce que c'est et comment cela fonctionne

Barbara Streisand
Barbara Streisandoriginal
2024-10-09 16:15:02270parcourir

Exploring Name Mangling in Python: What It Is and How It Works

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.

Qu'est-ce que la modification du nom

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.

Définition technique

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.

Pourquoi Python utilise-t-il la modification des noms

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.

Comment fonctionne la modification des noms

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.

Accéder au nom mutilé

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)

Quand Python modifie-t-il les noms

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.

Avantages et limites

Avantages

  • Aide à éviter le remplacement accidentel des attributs de classe dans les sous-classes
  • Fournit un mécanisme léger pour la confidentialité sans être trop restrictif.

Limites

  • Ce n'est pas vraiment privé : d'autres développeurs peuvent toujours accéder au nom mutilé s'ils savent comment le faire.
  • Peut rendre le débogage et la lecture du code plus complexes en cas de surutilisation.

_ 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!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn