Copyright © 2000 Pramode C E
Copyright © 2000 Martin Quinson
Article paru dans le n°54 de la Gazette Linux de juin 2000.
Cet article est publié selon les termes de la Open Publication License. La Linux Gazette n'est ni produite, ni sponsorisée, ni avalisée par notre hébergeur principal, SSC, Inc.
Table des matières
Les programmeurs C++ utilisent la « surcharge d'opérateurs » pour appliquer les opérations de base sur les classes définies par l'utilisateur. Par exemple, une classe de nombres complexes peut contenir un opérateur d'addition qui rend possible l'usage d'objets de type « complexe » dans une expression arithmétique, de la même manière que des nombres entiers ou flottants. Le langage Python offre le même genre de fonctionnalité de manière simple et élégante grâce aux attributs de méthode.
Cet article est une rapide introduction à certaines méthodes au travers de morceaux de code que j'ai écris en lisant le guide de références. Le code a été testé avec Python version 1.5.1.
Voyons une simple définition de classe en Python :
class toto: def __init__(self, n): print 'le constructeur est appelé' self.n = n def hello(self): print 'Bonjour, monde' def change(self, n): print 'Change self.n' self.n = n f = toto(10) # crée une instance de la classe foo avec un champ de données # 'n' ayant la valeur 10. print f.n # affiche 10. Python ne gère pas les contrôles d'accès aux # membres comme C++ le fait. f.m = 20 # Vous pouvez même ajouter de nouveaux champs ! f.hello() # affiche 'Bonjour, monde' toto.change(f, 40) print f.n # affiche 40
La méthode __init__
est similaire au « constructeur » de
C++. C'est une méthode spéciale appelée automatiquement à la
création de l'objet.
Remarquons que toutes les fonctions membres ont un argument
nommé « self » et représentant l'objet lui même. Ainsi, appeler
f.hello()
revient à appeler une méthode appartenant à la classe toto
avec l'objet f en premier paramètre. Ce paramètre est
habituellement nommé « self ». Bien qu'il soit possible de lui donner
n'importe quel nom, il est conseillé de suivre cette
convention. Les programmeurs C++ trouverons sans doute un rapport
entre « self » et le mot clé « this », qui est dans ce langage le
premier paramètre (caché) des invocations de méthodes.
Considérons la définition de classe suivante :
class toto: def __init__(self, n): self.n = n def __add__(self, right): t = toto(0) t.n = self.n + right.n return t
Maintenant, créons deux objets f1 et f2 de type « toto » et additionnons les :
f1 = toto(10) # f1.n vaut 10 f2 = toto(20) # f2.n vaut 20 f3 = f1 + f2 print f3.n # affiche 30
Que ce passe-t-il quand Python exécute f1+f2
? En fait,
l'interpréteur appelle simplement f1.__add__(f2)
. Ainsi, « self »
désigne f1
dans la fonction __add__
, et « right » désigne f2
.
Voyons une autre façon d'utiliser la fonction spéciale __add__
:
class toto: def __init__(self, n): self.n = n def __radd__(self, left): t = toto(0) t.n = self.n + left.n print 'left.n vaut', left.n return t f1 = toto(10) f2 = toto(20) f3 = f1 + f2 # affiche 'left.n vaut 10'
La différence est que dans ce cas, f1+f2
est converti en
f2.__add__(f1)
.
class toto: def __init__(self, n1, n2): self.n1 = n1 self.n2 = n2 def __str__(self): return 'Instance de toto:'+'n1='+`self.n1`+','+'n2='+`self.n2`
La classe toto définit une méthode spéciale appelée
__str__
. Voyons son usage dans le code de test suivant :
f1 = toto(10,20) print f1 # affiche 'Instance de toto : n1=10,n2=20'
Il existe aussi une méthode analogue nommée __repr__
. Veuillez
vous reporter au guide des références pour plus de détails.
Cette méthode est appelée quand on veut savoir si l'objet est
« vrai » ou « faux », par exemple quand on l'utilise dans un
test. Elle doit retourner la valeur 0 ou 1. Quand cette méthode
n'existe pas, __len__
est appelée. Si ni __nonzero__
ni __len__
n'existe, toutes les instances sont considérées vraies. Voici un
exemple de ceci :
class foo: def __nonzero__(self): return 0 class baz: def __len__(self): return 0 class abc: pass f1 = foo() f2 = baz() f3 = abc() if (not f1): print 'foo: faux' # affiche 'foo: faux' if (not f2): print 'baz: faux' # affiche 'baz: faux' if (not f3): print 'abc: faux' # n'affiche rien
Vous souhaitez que votre classe se comporte comme une liste ? La
principale caractéristique d'une liste (ou d'un tuple, ou plus
généralement une séquence) est qu'elle permet de faire de
l'indexage. C'est à dire que l'on peut écrire des choses comme :
print a[i]
. Il existe une méthode spéciale nommée
__getitem__
fait pour implanter l'indexage sur les objets définis
par l'utilisateur. Par exemple :
class toto: def __init__(self, limit): self.limit = limit def __getitem__(self, key): if ((key > self.limit-1) or (key < -(self.limit-1))): raise IndexError else: return 2*key f = toto(10) # f se comporte comme un tableau de 20 éléments. print f[0], f[1] # affiche 0, 2 print f[-3] # affiche -6 print f[10] # génère IndexError
D'autres méthodes existent pour implanter l'indexage :
__setitem__
, __delitem__
, __getslice__
, __setslice__
et
__delslice__
.
__getattr__(self,nom)
est appelé quand l'attribut « nom » est
introuvable. Cette méthode devrait soit lever une exception
AttributeError
ou renvoyer un attribut calculé.
class toto: def __getattr__(self, name): return 'attribut introuvable' f = toto() f.n = 100 print f.n # affiche 100 print f.m # affiche 'attribut introuvable'
Notons qu'il existe aussi une fonction
getattr(objet,nom)
. Ainsi,
getattr(f, 'n')
retourne 100, et
getattr(f,'m')
retourne la chaîne
« attribut introuvable ». Ce mécanisme permet de réaliser très
simplement des délégations :
class Boss: def __init__(self, délégué): self.d = délégué def credits(self): print "Je suis le grand chef, et j'ai fait moi même ces choses merveilleuses" def __getattr__(self, name): return getattr(self.d, name) class Esclave: def work(self): print "Gasp, je suis l'esclave, et il a fallu que je fasse tout ça" w = Esclave() b = Boss(w) b.credits() # affiche 'Je suis le grand chef, et j'ai fait moi même ces # choses merveilleuses' b.work() # Affiche 'Gasp, je suis l'esclave, et il a fallu que je fasse # tout ça'
La distribution vient avec une très bonne documentation (en anglais :), qui inclut un tutoriel, un guide de référence du langage et un guide de référence des bibliothèques. Si vous débutez en Python, vous devriez lire l'excellent tutoriel de Guido.Vous pouvez aussi parcourir les références du langage et les références des bibliothèques. Cet article a été traduit avec l'aide des références du langage.
L'adaptation française de ce document a été réalisée dans le cadre du Projet de traduction de la Gazette Linux.
Vous pourrez lire d'autres articles traduits et en apprendre plus sur ce projet en visitant notre site : http://www.traduc.org/Gazette_Linux.
Si vous souhaitez apporter votre contribution, n'hésitez pas à nous rejoindre, nous serons heureux de vous accueillir.