IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Classmethod vs variable de classe


Sujet :

Python

  1. #1
    Membre actif
    Homme Profil pro
    Chômeur professionnel
    Inscrit en
    Novembre 2020
    Messages
    122
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Algérie

    Informations professionnelles :
    Activité : Chômeur professionnel

    Informations forums :
    Inscription : Novembre 2020
    Messages : 122
    Par défaut Classmethod vs variable de classe
    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.

  2. #2
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 720
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 720
    Par défaut
    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:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    class A:
          toto = None
          def xyz(a, b, c):
                pass
    et ils sont "de la classe" car accessibles par toutes les instances de la classe.

    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
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 830
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 830
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Yuseph Voir le message
    Wesh les mecs,
    Dit-il l'index et le majeur levés en signe de victoire. Ok, salut à toi aussi...

    Citation Envoyé par Yuseph Voir le message
    J ai rien compris la difference entre variable de classe et classmethod.
    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…
    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
    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.
    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" :
    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’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.
    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.
    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'>
    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
    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]

Discussions similaires

  1. Accès a des variables de classes
    Par lalouve dans le forum Général JavaScript
    Réponses: 9
    Dernier message: 11/05/2006, 16h48
  2. variable de classe en Python
    Par Thierry Chappuis dans le forum Général Python
    Réponses: 5
    Dernier message: 09/02/2006, 22h06
  3. Variable de classe JPanel
    Par Janitrix dans le forum AWT/Swing
    Réponses: 4
    Dernier message: 11/12/2005, 17h50
  4. débutant:utilisation de variable entre classe
    Par troojan dans le forum MFC
    Réponses: 1
    Dernier message: 07/12/2005, 23h31
  5. Réponses: 6
    Dernier message: 23/09/2005, 12h54

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo