Objets ====== En fait, *tout ce qu'on manipule en Python* est un objet. Et tous les objets sont toujours des instances d'une classe - on peut accéder à la classe qui a servi à instancier un objet avec la fonction ``type``, par exemple:: class MaClasse: pass mon_instance = MaClasse() print(type(mon_instance)) # Affiche: # Mais aussi:: print(type(2)) # affiche: int print(type("bonjour")) # affiche: str Donc en Python, les entiers sont des instances de la classe ``int``, et les strings des instances de la classe ``str``. Ainsi, vous pouvez voir l'expression ``x = str(y)`` de deux façons: * Soit on appelle la fonction native ``str`` pour convertir ``y`` en string * Soit on crée une nouvelle instance de la classe ``str`` en appelant le constructeur de la classe ``str`` avec ``y`` en argument. Notez que ça ne s'arrète pas là:: def ma_fonction(): pass print(type(ma_fonction)) # affiche: function class MaClasse: def ma_méthode(self): pass mon_instance = MaClasse() print(type(mon_instance.ma_méthode)) # affiche: method import sys print(type(sys)) # affiche: module Et même:: print(type(MaClasse)) # affiche: type print(type(type)) # affiche: type Et oui, les classes elles-mêmes sont des instances de classe! (la classe ``type``) Du coup en Python, le terme 'objet' désigne *toujours* une instance de classe - même ``None`` est une instance d'une classe (elle s'appelle ``NoneType``). Ordre de résolution -------------------- Il est temps de revenir sur l'évaluation des expressions impliquant des attributs. On a vu trois systèmes différents: Appeler une fonction définie dans un module:: import mon_module mon_module.ma_fonction() Appeler une méthode d'instance définie dans une classe:: mon_instance = MaClasse() mon_instance.ma_méthode() Appeler une méthode de classe définie dans une classe:: MaClasse.ma_méthod_de_classe() D'après ce qu'on a vu dans la section précédente, on sait maintenant que dans tous les cas, à gauche du point se situe un objet, et que tous les objets sont des instances d'une classe (appelé le "type" de l'objet). Pour évaluer l'expression ``mon_objet.mon_attribut``, où `mon_objet`` est une instance de ``mon_type``, Python cherche toujours l'attribut dans deux endroits: * D'abord en tant qu'attribut de l'instance ``mon_objet`` * Ensuite, en tant qu'attribut de la classe ``mon_type`` La recherche se poursuit ainsi en suivant toutes les classe parentes de ``mon_type``. On peut voir ce mécanisme en action dans le code suivant:: class A: def f1(self): print("f1 dans A") def f2(self): print("f2") class B(A): @classmethod def f3(cls): print("f3") def f1(self): print("f1 dans B") b = B() b.f1() b.f3() b.f2() # affiche: # f1 dans B # f3 # f2 Conclusion ------------ Maintenant vous devriez comprendre pourquoi on dit parfois qu'en Python, **tout est objet**. Dans un prochain chapitre, on expliquera pourquoi en plus de cela on peut dire qu'en Python, **tout est dictionnaire**.