Salut,
int
implémente numbers.Integral
qui lui même implémente numbers.Rational
d’où vient sa propriété numerator
et denominator
. L’intérêt de ça, c’est surtout que si tu veux écrire une fonction capable de gérer des nombres rationels (pour faire du calcul sur des fractions), tu peux lui filer n’importe quel objet qui implémente l’interface numbers.Rational
. Tu n’as alors pas à te soucier de savoir si l’objet passé est un int
ou bien un nombre rationnel plus compliqué, tu peux directement travailler avec sa propriété denominator
par exemple.
Tu noteras que de la même façon, Rational
implémente Real
, qui lui même implémente Complex
. Ça veut dire que ton entier a une propriété imag
(toujours nulle) et une propriété real
(la valeur de l’entier). Ça veut dire que si tu écris une fonction qui attend des nombres complexes, tu peux prendre un entier en argument et le manipuler directement comme si c’était un complexe.
Cette ubiquité d’interfaces variées qui définissent comment tu peux manipuler les objets est la façon dont Python gère l’écriture de fonctions polymorphiques (capables de gérer plusieurs types différents en entrée). C’est pratique dans le sens où tu peux écrire beaucoup de code sans avoir à réfléchir au typage au-delà d’interfaces plutôt génériques ("tout ce que je veux, c’est un truc qui ressemble à un nombre"). Évidemment, c’est pas parfait : comme tout (même le typage) est géré dynamiquement (à l’exécution), ça a un coût au runtime et ne vient qu’avec des garanties statiques limitées (et seulement avec l’aide d’outils comme mypy
).
Bref, cette façon de voir les choses qui est de dire que ce qui importe n’est pas le type d’une valeur, mais plutôt l’interface qu’elle offre s’appelle le duck typing.