ProgrammationDéveloppeur Python

Expliquez comment le polymorphisme est mis en œuvre en Python, quelles formes existent et quels sont les nuances de la typage dynamique en pratique ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

Polymorphisme — principe fondamental de la programmation orientée objet, qui permet aux objets de structures différentes de réaliser la même interface, et donc de fonctionner de manière interchangeable. En Python, avec typage dynamique, le polymorphisme est mis en place de manière très flexible.

Contexte

Dans les langages avec typage statique strict (Java, C++), la prise en charge du polymorphisme nécessite la déclaration d'interfaces ou de classes abstraites. En Python — grâce au duck typing — le polymorphisme n'est pas lié à la hiérarchie d'héritage ni même à l'interface. L'essentiel est que l'objet supporte les méthodes/attributs requis.

Problème

D'une part, cela rend le langage flexible et pratique. D'autre part — cela augmente la probabilité d'erreurs à l'exécution en raison de fautes de frappe ou de l'absence de la méthode requise, qui ne se manifesteront qu'à l'exécution du code.

Solution

En Python, on distingue :

  • Polymorphisme ordinaire (classique) par l'héritage et la redéfinition des méthodes :
class Animal: def speak(self): raise NotImplementedError class Dog(Animal): def speak(self): return 'Woof!' class Cat(Animal): def speak(self): return 'Meow!' def animal_voice(animal): print(animal.speak()) animal_voice(Dog()) # Woof! animal_voice(Cat()) # Meow!
  • Duck Typing — si une classe possède la méthode requise, elle conviendra à toute fonction attendant cette méthode, peu importe son héritage :
class Duck: def quack(self): return 'Quack!' def make_quack(animal): print(animal.quack()) make_quack(Duck()) # Quack!
  • Imitation d'interface — via abc.ABC et @abstractmethod, on peut formaliser que les classes doivent réaliser certaines méthodes.

Caractéristiques clés :

  • Absence d'obligation de maintenir une hiérarchie d'héritage rigide.
  • Possibilité de remplacer des objets à l'exécution, s'ils supportent la bonne interface.
  • Les erreurs de non-conformité d'interface ne se révèlent qu'à l'exécution.

Questions pièges.

L'héritage est-il le seul moyen d'assurer le polymorphisme en Python ?

Non. Grâce au duck typing, toute fonction peut accepter un objet avec les méthodes requises indépendamment de sa classe ou de sa hiérarchie.

Peut-on considérer comme polymorphisme le simple fait que la signature correspond au nom de la méthode, et non à son contenu ?

Non. Si un objet supporte la méthode requise mais que sa sémantique diffère de celle attendue, des bugs peuvent apparaître. Le polymorphisme réussit seulement lorsque l'interface et le sens coïncident.

Un classe abstraite protège-t-elle contre les erreurs d'une mauvaise implémentation d'interface dans les classes dérivées ?

Seulement partiellement. Si un héritier n'implémente pas la méthode abstraite, un TypeError se produira lors de la tentative de création d'une instance. Mais s'il l'implémente avec des erreurs logiques, des erreurs peuvent survenir.

Erreurs courantes et anti-patrons

  • Implémentation incorrecte de l'interface sans respecter la sémantique de la méthode.
  • Dépendance au duck typing sans tests appropriés, entraînant des erreurs à l'exécution.
  • Attente d'un typage strict (comme dans les langages à typage statique), alors que Python ne garantit pas cela.

Exemple de la vie réelle

Cas négatif

Une bibliothèque de journalisationintègre une classe tierce, qui possède une méthode log(), mais elle renvoie un objet de données au lieu d'écrire dans le journal. Les erreurs se manifestent uniquement lors de l'exploitation.

Avantages :

  • Intégration rapide de diverses classes sans bureaucratie inutile.

Inconvénients :

  • Bugs silencieux découverts uniquement à l'exécution, souvent déjà en production.

Cas positif

Les classes sont accompagnées de tests, l'interface est formalisée par le biais d'une classe de base abstraite et @abstractmethod, la documentation décrit la sémantique des méthodes.

Avantages :

  • Clarté, prévention des erreurs les plus fréquentes.
  • Augmentation de la fiabilité du code.

Inconvénients :

  • Discipline de développement plus stricte, plus de code et de documentation.