Wesh les mecs,
J ai rien compris la difference entre variable de classe et classmethod. Dans les deux cas il faut lier une methode � une instance. Jvois pas en quoi classmethod est plus global.
Wesh les mecs,
J ai rien compris la difference entre variable de classe et classmethod. Dans les deux cas il faut lier une methode � une instance. Jvois pas en quoi classmethod est plus global.
Salut,
Avec Python, tout est "attribut"... et la diff�rence entre attribut et m�thode est qu'une m�thode est, � priori, un "callable" (mot plus g�n�rique que fonction appelable).
Quand on d�finit une classe, tous les attributs sont des attributs de classe:
et ils sont "de la classe" car accessibles par toutes les instances de la classe.
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4 class A: toto = None def xyz(a, b, c): pass
Pour le reste, c'est de la r�-�criture.
Imaginons une instance de A nomm�e aa.
aa.xyz sera un objet de type "m�thode" i.e. une fonction (A.xyz) associ�e � un objet (aa).
aa.xyz(...) sera un appel de la fonction A.xyz associ�e � l'objet aa avec les param�tres ...
Le boulot de l'interpr�teur sera de savoir par quoi evremplacer le premier argument pour appeler la fonction:
- staticmethod: on laisse tel quel donc c'est l'appel de AA.xyz(...)
- classmethod: on ajoute la classe comme premier argument: AA.xyz(A, ...)
- methode normale: on ajoute l'instance: AA.xyz(aa,...)
Et l'int�r�t de tout ce bazar est d'�tre consistant vis � vis de l'h�ritage.
- W
Dit-il l'index et le majeur lev�s en signe de victoire. Ok, salut � toi aussi...
Je pense (enfin j'esp�re) que c'est surtout l'utilit� de l'instruction "classmethod" que tu n'as pas compris.
La classmethod r�cup�re le type de l'objet qui l'invoque, ce qui permet de suivre l'�volution de ce type dans le cas d'un h�ritage (c'est alors le type h�rit� qui est r�cup�r�)
Prenons un exemple simple : un objet permettant de manipuler une date�
L�utilisateur qui veut utiliser cet objet doit alors l�instancier selon une convention bien d�finie en lui passant les trois caract�ristiques d�une date (jour, mois et ann�e) en argument.
Code python : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
6
7
8
9 class date: def __init__(self, jj, mm, aa): self.jj=jj self.mm=mm self.aa=aa >>> a=date(1, 1, 2000) >>> print(a.jj, a.mm, a.aa) 1 1 2000
Si maintenant l�utilisateur recevait une date sous forme texte ("jj/mm/aaaa"), il devra alors �clater ce texte pour pouvoir r�cup�rer ses divers �l�ments avant de pouvoir cr�er son objet.
Si ce comportement se g�n�ralise, il peut alors avoir envie de modifier son objet pour qu�il puisse absorber ou une date classique ou une date texte. Petit travail facile de factorisation qui, en retour, lui simplifiera ensuite grandement l��criture du code qui utilisera cet objet.
Une premi�re solution sera alors de modifier __init__() pour l�autoriser � absorber les deux types de param�tres. Faisable mais si demain un 3� format diff�rent se pr�sente, et un 4� apr�s-demain�?
Une seconde solution sera de cr�er une m�thode statique renvoyant un nouvel objet "date" :
L�avantage c�est que si un troisi�me format d�entr�e arrive demain, on pourra toujours rajouter une autre m�thode "fromXXX", "fromYYY" et ainsi de suite.
Code python : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
6
7
8
9
10
11
12
13 class date: def __init__(self, jj, mm, aa): self.jj=jj self.mm=mm self.aa=aa @staticmethod def fromString(string): (jj, mm, aa)=string.split("/") return date(jj, mm, aa) >>> a=date.fromString("1/1/2000") >>> print(a.jj, a.mm, a.aa) 1 1 2000
L�inconv�nient c'est que la m�thode utilise le nom de l�objet de fa�on litt�rale. D�j� cela induit des contraintes d��volutivit� (si le nom change demain�) et surtout peut poser des soucis li�s � l�h�ritage (la m�thode renvoie un objet "date" alors que l�utilisateur pourrait avoir envie d�utiliser un objet h�rit� de "date").
Code python : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 class date: def __init__(self, jj, mm, aa): self.jj=jj self.mm=mm self.aa=aa @staticmethod def fromString(string): return date(*string.split("/")) class subDate(date): pass >>> a=date.fromString("1/1/2000") >>> type(a) <class '__main__.date'> >>> b=subDate.fromString("1/1/3000") >>> type(b) <class '__main__.date'> # Il voulait créer un subDate !!!
La troisi�me solution sera d�utiliser une fonction encapsul�e dans une surcouche "classmethod()". Cette fonction recevra alors en premier param�tre le nom de la classe qui l�invoque (g�n�ralement on stocke ce nom dans un param�tre conventionnellement nomm� "cls"). L�utilisateur pourra alors utiliser ce nom de classe pour g�n�rer l�objet qui en d�coule.
Cette solution r�pond aux m�mes contraintes que la solution pr�c�dente mais offre l�avantage de suivre l��volution du code (si le nom de l�objet change, cela se fera de fa�on transparente sans avoir besoin de rev�rifier tout son contenu) ainsi que les contraintes li�es � l'h�ritage.
Code python : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
6
7
8
9
10
11
12 class date: def __init__(self, jj, mm, aa): self.jj=jj self.mm=mm self.aa=aa @classmethod def fromString(cls, string): return cls(*string.split("/")) >>> a=date.fromString("1/1/2000") >>> type(a) <class '__main__.date'>
Code python : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 class date: def __init__(self, jj, mm, aa): self.jj=jj self.mm=mm self.aa=aa @classmethod def fromString(cls, string): return cls(*string.split("/")) class subDate(date): pass >>> a=date.fromString("1/1/2000") >>> type(a) <class '__main__.date'> >>> b=subDate.fromString("1/1/3000") >>> type(b) <class '__main__.subDate'> # Il a bien son objet subDate !!!
Mon Tutoriel sur la programmation �Python�
Mon Tutoriel sur la programmation �Shell�
Sinon il y en a pleins d'autres. N'oubliez pas non plus les diff�rentes faq disponibles sur ce site
Et on poste ses codes entre balises [code] et [/code]
Partager