Comment les objets sont représentés

PythonPythonBeginner
Pratiquer maintenant

This tutorial is from open-source community. Access the source code

💡 Ce tutoriel est traduit par l'IA à partir de la version anglaise. Pour voir la version originale, vous pouvez cliquer ici

Introduction

Dans ce laboratoire, vous apprendrez comment les objets Python sont représentés en interne et comprendrez les mécanismes d'affectation et de recherche d'attributs. Ces concepts sont essentiels pour saisir comment Python gère les données et le comportement au sein des objets.

De plus, vous explorerez la relation entre les classes et les instances et examinerez le rôle des définitions de classe en programmation orientée objet. Cette connaissance améliorera votre compréhension des fonctionnalités orientées objet de Python.

Ceci est un Guided Lab, qui fournit des instructions étape par étape pour vous aider à apprendre et à pratiquer. Suivez attentivement les instructions pour compléter chaque étape et acquérir une expérience pratique. Les données historiques montrent que c'est un laboratoire de niveau débutant avec un taux de réussite de 94%. Il a reçu un taux d'avis positifs de 93% de la part des apprenants.

Création d'une classe simple pour les actions

Dans cette étape, nous allons créer une classe simple pour représenter une action. Comprendre comment créer des classes est fondamental en Python, car cela nous permet de modéliser des objets du monde réel et leurs comportements. Cette classe simple pour les actions sera notre point de départ pour explorer le fonctionnement interne des objets Python.

Pour commencer, nous devons ouvrir un shell interactif Python. Le shell interactif Python est un excellent endroit pour expérimenter avec le code Python. Vous pouvez taper et exécuter des commandes Python une par une. Pour l'ouvrir, tapez la commande suivante dans le terminal :

python3

Une fois que vous avez entré la commande, vous verrez l'invite Python (>>>). Cela indique que vous êtes maintenant dans le shell interactif Python et que vous pouvez commencer à écrire du code Python.

Maintenant, définissons une classe SimpleStock. Une classe en Python est comme un modèle pour créer des objets. Elle définit les attributs (données) et les méthodes (fonctions) que les objets de cette classe auront. Voici comment définir la classe SimpleStock avec les attributs et les méthodes nécessaires :

>>> class SimpleStock:
...     def __init__(self, name, shares, price):
...         self.name = name
...         self.shares = shares
...         self.price = price
...     def cost(self):
...         return self.shares * self.price
...

Dans le code ci - dessus, la méthode __init__ est une méthode spéciale dans les classes Python. C'est ce qu'on appelle un constructeur, et il est utilisé pour initialiser les attributs de l'objet lorsqu'un objet est créé. Le paramètre self fait référence à l'instance de la classe qui est en cours de création. La méthode cost calcule le coût total des actions en multipliant le nombre d'actions par le prix unitaire.

Après avoir défini la classe, nous pouvons créer des instances de la classe SimpleStock. Une instance est un objet réel créé à partir du modèle de la classe. Créons deux instances pour représenter différentes actions :

>>> goog = SimpleStock('GOOG', 100, 490.10)
>>> ibm = SimpleStock('IBM', 50, 91.23)

Ces instances représentent 100 actions de Google au prix de 490,10 $ par action et 50 actions d'IBM au prix de 91,23 $ par action. Chaque instance a son propre ensemble de valeurs d'attributs.

Vérifions que nos instances fonctionnent correctement. Nous pouvons le faire en vérifiant leurs attributs et en calculant leur coût. Cela nous aidera à confirmer que la classe et ses méthodes fonctionnent comme prévu.

>>> goog.name
'GOOG'
>>> goog.shares
100
>>> goog.price
490.1
>>> goog.cost()
49010.0
>>> ibm.cost()
4561.5

La méthode cost() multiplie le nombre d'actions par le prix unitaire pour calculer le coût total de détention de ces actions. En exécutant ces commandes, nous pouvons voir que les instances ont les bonnes valeurs d'attributs et que la méthode cost calcule le coût avec précision.

Exploration du dictionnaire interne des objets

En Python, les objets sont un concept fondamental. Un objet peut être considéré comme un conteneur qui stocke des données et a certains comportements. L'un des aspects intéressants des objets Python est la manière dont ils stockent leurs attributs. Les attributs sont comme des variables appartenant à un objet. Python stocke ces attributs dans un dictionnaire spécial, accessible via l'attribut __dict__. Ce dictionnaire fait partie intégrante de l'objet, et c'est là que Python garde la trace de toutes les données associées à cet objet.

Regardons de plus près cette structure interne en utilisant nos instances SimpleStock. En Python, une instance est un objet individuel créé à partir d'une classe. Par exemple, si SimpleStock est une classe, goog et ibm sont des instances de cette classe.

Pour voir le dictionnaire interne de ces instances, nous pouvons utiliser le shell interactif Python. Le shell interactif Python est un excellent outil pour tester rapidement du code et voir les résultats. Dans le shell interactif Python, tapez les commandes suivantes pour inspecter l'attribut __dict__ de nos instances :

>>> goog.__dict__
{'name': 'GOOG', 'shares': 100, 'price': 490.1}
>>> ibm.__dict__
{'name': 'IBM', 'shares': 50, 'price': 91.23}

Lorsque vous exécutez ces commandes, la sortie montre que chaque instance a son propre dictionnaire interne. Ce dictionnaire contient tous les attributs de l'instance. Par exemple, dans l'instance goog, les attributs name, shares et price sont stockés dans le dictionnaire avec leurs valeurs correspondantes. C'est ainsi que Python implémente les attributs des objets en coulisse. Chaque objet a un dictionnaire privé qui contient tous ses attributs.

Il est important de comprendre ce que l'attribut __dict__ révèle sur l'implémentation interne de nos objets :

  1. Les clés du dictionnaire correspondent aux noms des attributs. Par exemple, dans l'instance goog, la clé 'name' correspond à l'attribut name de l'objet.
  2. Les valeurs du dictionnaire sont les valeurs des attributs. Ainsi, la valeur 'GOOG' est la valeur de l'attribut name pour l'instance goog.
  3. Chaque instance a son propre __dict__ distinct. Cela signifie que les attributs d'une instance sont indépendants des attributs d'une autre instance. Par exemple, l'attribut shares de l'instance goog peut être différent de l'attribut shares de l'instance ibm.

Cette approche basée sur les dictionnaires permet à Python d'être très flexible avec les objets. Comme nous le verrons dans l'étape suivante, nous pouvons utiliser cette flexibilité pour modifier et accéder aux attributs des objets de diverses manières.

Ajout et modification d'attributs d'objet

En Python, les objets sont implémentés sur la base de dictionnaires. Cette implémentation confère à Python un haut degré de flexibilité lorsqu'il s'agit de gérer les attributs des objets. Contrairement à certains autres langages de programmation, Python ne limite pas les attributs d'un objet aux seuls attributs définis dans sa classe. Cela signifie que vous pouvez ajouter de nouveaux attributs à un objet à tout moment, même après sa création.

Explorons cette flexibilité en ajoutant un nouvel attribut à l'une de nos instances. Supposons que nous ayons une instance nommée goog d'une classe. Nous allons lui ajouter un attribut date :

>>> goog.date = "6/11/2007"
>>> goog.__dict__
{'name': 'GOOG', 'shares': 100, 'price': 490.1, 'date': '6/11/2007'}

Ici, nous avons ajouté un nouvel attribut date à l'instance goog. Notez que cet attribut date n'était pas défini dans la classe SimpleStock. Ce nouvel attribut n'existe que sur l'instance goog. Pour confirmer cela, vérifions l'instance ibm :

>>> ibm.__dict__
{'name': 'IBM', 'shares': 50, 'price': 91.23}
>>> hasattr(ibm, 'date')
False

Comme nous pouvons le voir, l'instance ibm n'a pas l'attribut date. Cela montre trois caractéristiques importantes des objets Python :

  1. Chaque instance a son propre ensemble unique d'attributs.
  2. Les attributs peuvent être ajoutés à un objet après sa création.
  3. L'ajout d'un attribut à une instance n'affecte pas les autres instances.

Maintenant, essayons une autre façon d'ajouter un attribut. Au lieu d'utiliser la notation par point, nous allons manipuler directement le dictionnaire sous - jacent de l'objet. En Python, chaque objet a un attribut spécial __dict__ qui stocke tous ses attributs sous forme de paires clé - valeur.

>>> goog.__dict__['time'] = '9:45am'
>>> goog.time
'9:45am'
>>> goog.__dict__
{'name': 'GOOG', 'shares': 100, 'price': 490.1, 'date': '6/11/2007', 'time': '9:45am'}

En modifiant directement le dictionnaire __dict__, nous avons ajouté un nouvel attribut time à l'instance goog. Lorsque nous accédons à goog.time, Python cherche la clé 'time' dans le dictionnaire __dict__ et renvoie sa valeur correspondante.

Ces exemples illustrent que les objets Python sont essentiellement des dictionnaires avec quelques fonctionnalités supplémentaires. La flexibilité des objets Python permet des modifications dynamiques, ce qui est très puissant et pratique en programmation.

Comprendre la relation entre les classes et les instances

Maintenant, nous allons explorer comment les classes et les instances sont liées en Python, et comment la recherche de méthodes fonctionne. C'est un concept important car il vous aide à comprendre comment Python trouve et utilise les méthodes et les attributs lorsque vous travaillez avec des objets.

Tout d'abord, vérifions à quelle classe appartiennent nos instances. Savoir la classe d'une instance est crucial car cela nous indique où Python cherchera les méthodes et les attributs liés à cette instance.

>>> goog.__class__
<class '__main__.SimpleStock'>
>>> ibm.__class__
<class '__main__.SimpleStock'>

Les deux instances ont une référence vers la classe SimpleStock. Cette référence est comme un pointeur que Python utilise lorsqu'il a besoin de rechercher des méthodes. Lorsque vous appelez une méthode sur une instance, Python utilise cette référence pour trouver la définition appropriée de la méthode.

Lorsque vous appelez une méthode sur une instance, Python suit ces étapes :

  1. Il cherche l'attribut dans le __dict__ de l'instance. Le __dict__ d'une instance est comme une zone de stockage où tous les attributs spécifiques à l'instance sont conservés.
  2. S'il n'est pas trouvé, il vérifie le __dict__ de la classe. Le __dict__ de la classe stocke tous les attributs et les méthodes qui sont communs à toutes les instances de cette classe.
  3. S'il est trouvé dans la classe, il renvoie cet attribut.

Voyons cela en action. Tout d'abord, vérifions que la méthode cost n'est pas dans les dictionnaires des instances. Cette étape nous aide à comprendre que la méthode cost n'est pas spécifique à chaque instance mais est définie au niveau de la classe.

>>> 'cost' in goog.__dict__
False
>>> 'cost' in ibm.__dict__
False

Alors, d'où vient la méthode cost ? Vérifions la classe. En regardant le __dict__ de la classe, nous pouvons découvrir où la méthode cost est définie.

>>> SimpleStock.__dict__['cost']
<function SimpleStock.cost at 0x7f...>

La méthode est définie dans la classe, pas dans les instances. Lorsque vous appelez goog.cost(), Python ne trouve pas cost dans goog.__dict__, donc il cherche dans SimpleStock.__dict__ et la trouve là.

Vous pouvez en fait appeler la méthode directement depuis le dictionnaire de la classe, en passant l'instance comme premier argument (qui devient self). Cela montre comment Python appelle les méthodes en interne lorsque vous utilisez la syntaxe normale instance.méthode().

>>> SimpleStock.__dict__['cost'](goog)
49010.0
>>> SimpleStock.__dict__['cost'](ibm)
4561.5

C'est essentiellement ce que Python fait en coulisse lorsque vous appelez goog.cost().

Maintenant, ajoutons un attribut de classe. Les attributs de classe sont partagés par toutes les instances. Cela signifie que toutes les instances de la classe peuvent accéder à cet attribut, et qu'il n'est stocké qu'une seule fois au niveau de la classe.

>>> SimpleStock.exchange = 'NASDAQ'
>>> goog.exchange
'NASDAQ'
>>> ibm.exchange
'NASDAQ'

Les deux instances peuvent accéder à l'attribut exchange, mais il n'est pas stocké dans leurs dictionnaires individuels. Vérifions cela en vérifiant les dictionnaires de l'instance et de la classe.

>>> 'exchange' in goog.__dict__
False
>>> 'exchange' in SimpleStock.__dict__
True
>>> SimpleStock.__dict__['exchange']
'NASDAQ'

Cela démontre que :

  1. Les attributs de classe sont partagés par toutes les instances. Toutes les instances peuvent accéder au même attribut de classe sans avoir leur propre copie.
  2. Python vérifie d'abord le dictionnaire de l'instance, puis le dictionnaire de la classe. C'est l'ordre dans lequel Python cherche les attributs lorsque vous essayez de les accéder sur une instance.
  3. Les classes servent de dépôt pour les données et les comportements (méthodes) partagés. La classe stocke tous les attributs et les méthodes communs qui peuvent être utilisés par toutes ses instances.

Si nous modifions un attribut d'instance avec le même nom, il masque l'attribut de classe. Cela signifie que lorsque vous accédez à l'attribut sur cette instance, Python utilisera la valeur spécifique à l'instance au lieu de la valeur au niveau de la classe.

>>> ibm.exchange = 'NYSE'
>>> ibm.exchange
'NYSE'
>>> goog.exchange  ## Toujours en utilisant l'attribut de classe
'NASDAQ'
>>> ibm.__dict__['exchange']
'NYSE'

Maintenant, ibm a son propre attribut exchange qui masque l'attribut de classe, tandis que goog utilise toujours l'attribut de classe.

Résumé

Dans ce laboratoire, vous avez appris le fonctionnement interne du système d'objets de Python et plusieurs concepts clés. Premièrement, les objets Python stockent les attributs dans un dictionnaire accessible via l'attribut __dict__, offrant ainsi une grande flexibilité. Deuxièmement, vous avez compris le fonctionnement de l'affectation et de la recherche d'attributs, y compris l'ajout dynamique d'attributs et l'ordre de vérification des attributs.

De plus, vous avez exploré la relation entre les classes et les instances. Les classes contiennent les données et les comportements partagés, tandis que les instances maintiennent leur propre état. Vous avez également découvert le fonctionnement des appels de méthodes, où les méthodes de la classe agissent sur les instances via le paramètre self. Comprendre ces concepts approfondit votre compréhension du modèle de programmation orientée objet (OOP) de Python et est utile pour le débogage, la conception de hiérarchies de classes et l'apprentissage des fonctionnalités avancées.