python example - Quelle est la différence entre @staticmethod et @classmethod?




and call (20)

Un rapide aperçu des méthodes identiques dans iPython révèle que @staticmethodles gains de performance sont marginaux (en nanosecondes), mais sinon, cela ne semble avoir aucune fonction. En outre, les gains de performances seront probablement annulés par le travail supplémentaire de traitement de la méthode staticmethod()lors de la compilation (ce qui se produit avant toute exécution de code lorsque vous exécutez un script).

Par souci de lisibilité du code, je l’éviterais à @staticmethodmoins que votre méthode ne soit utilisée pour des tâches lourdes, où les nanosecondes comptent.

Quelle est la différence entre une fonction décorée avec @staticmethod et une fonction décorée avec @classmethod ?


Une méthode statique est une méthode qui ignore tout de la classe ou de l'instance sur laquelle elle a été appelée. Il récupère simplement les arguments qui ont été passés, pas de premier argument implicite. Il est fondamentalement inutile en Python - vous pouvez simplement utiliser une fonction de module au lieu d’une méthode statique.

Une méthode de classe , en revanche, est une méthode qui obtient en premier argument la classe sur laquelle elle a été appelée ou la classe de l'instance sur laquelle elle a été appelée. Ceci est utile lorsque vous souhaitez que la méthode soit une fabrique pour la classe: étant donné qu'elle obtient comme premier argument la classe sur laquelle elle a été appelée, vous pouvez toujours instancier la bonne classe, même lorsque des sous-classes sont impliquées. Observez par exemple comment dict.fromkeys() , une méthode de classe, renvoie une instance de la sous-classe lorsqu'il est appelé dans une sous-classe:

>>> class DictSubclass(dict):
...     def __repr__(self):
...         return "DictSubclass"
... 
>>> dict.fromkeys("abc")
{'a': None, 'c': None, 'b': None}
>>> DictSubclass.fromkeys("abc")
DictSubclass
>>> 

Les méthodes de classe, comme leur nom l'indique, sont utilisées pour modifier les classes et non les objets. Pour modifier les classes, ils modifieront les attributs de classe (pas les attributs d'objet), car c'est ainsi que vous mettez à jour les classes. C'est la raison pour laquelle les méthodes de classe prennent la classe (généralement désignée par 'cls') comme premier argument.

class A(object):
    m=54

    @classmethod
    def class_method(cls):
        print "m is %d" % cls.m

Les méthodes statiques, quant à elles, permettent d’exécuter des fonctionnalités qui ne sont pas liées à la classe, c’est-à-dire qu’elles ne liront ni n’écriront de variables de classe. Par conséquent, les méthodes statiques ne prennent pas les classes comme arguments. Ils sont utilisés pour que les classes puissent exécuter des fonctionnalités qui ne sont pas directement liées à l'objectif de la classe.

class X(object):
    m=54 #will not be referenced

    @staticmethod
    def static_method():
        print "Referencing/calling a variable or function outside this class. E.g. Some global variable/function."

Le guide définitif sur l’utilisation des méthodes statiques, de classe ou abstraites en Python est un bon lien pour cette rubrique, et résumez-le comme suit.

@staticmethod fonction @staticmethod n'est rien d'autre qu'une fonction définie dans une classe. Il est appelable sans instancier d'abord la classe. Sa définition est immuable par héritage.

  • Python n'a pas besoin d'instancier une méthode liée pour object.
  • Cela facilite la lisibilité du code et ne dépend pas de l'état de l'objet lui-même;

@classmethod fonction @classmethod également être appelée sans instancier la classe, mais sa définition suit la classe Sub, et non la classe Parent, via l'héritage, pouvant être remplacée par la sous-classe. En effet, le premier argument de la fonction @classmethod doit toujours être cls (classe).

  • Les méthodes d'usine , qui sont utilisées pour créer une instance pour une classe en utilisant par exemple une sorte de pré-traitement.
  • Méthodes statiques appelant des méthodes statiques : si vous divisez une méthode statique en plusieurs méthodes statiques, vous ne devez pas coder en dur le nom de la classe, mais utiliser des méthodes de classe.

@staticmethod désactive simplement la fonction par défaut en tant que descripteur de méthode. classmethod encapsule votre fonction dans un conteneur appelable qui passe une référence à la classe propriétaire en premier argument:

>>> class C(object):
...  pass
... 
>>> def f():
...  pass
... 
>>> staticmethod(f).__get__(None, C)
<function f at 0x5c1cf0>
>>> classmethod(f).__get__(None, C)
<bound method type.f of <class '__main__.C'>>

En fait, classmethod a une surcharge d'exécution mais permet d'accéder à la classe propriétaire. Sinon, je vous recommande d'utiliser une métaclasse et de placer les méthodes de classe sur cette métaclasse:

>>> class CMeta(type):
...  def foo(cls):
...   print cls
... 
>>> class C(object):
...  __metaclass__ = CMeta
... 
>>> C.foo()
<class '__main__.C'>

méthode de classe vs méthode statique en Python

Méthode de classe

Le décorateur @classmethod est un décorateur de fonction intégré qui est une expression qui est évaluée après la définition de votre fonction. Le résultat de cette évaluation assombrit la définition de votre fonction.

Une méthode de classe reçoit la classe comme premier argument implicite, tout comme une méthode d'instance reçoit l'instance

Syntaxe:

class C(object):
    @staticmethod
    def fun(arg1, arg2, ...):
        ...
returns: a static method for function fun.
  • Une méthode de classe est une méthode liée à la classe et non à l'objet de la classe.
  • Ils ont accès à l'état de la classe car il faut un paramètre de classe qui pointe vers la classe et non l'instance de l'objet.
  • Il peut modifier un état de classe qui s'appliquerait à toutes les instances de la classe. Par exemple, il peut modifier une variable de classe qui sera applicable à toutes les instances.

Méthode statique

Une méthode statique ne reçoit pas de premier argument implicite.

Syntaxe:

# Python program to demonstrate 
# use of class method and static method.
from datetime import date

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    # a class method to create a Person object by birth year.
    @classmethod
    def fromBirthYear(cls, name, year):
        return cls(name, date.today().year - year)

    # a static method to check if a Person is adult or not.
    @staticmethod
    def isAdult(age):
        return age > 18

person1 = Person('mayank', 21)
person2 = Person.fromBirthYear('mayank', 1996)

print person1.age
print person2.age

# print the result
print Person.isAdult(22)
  • Une méthode statique est également une méthode liée à la classe et non à l'objet de la classe.
  • Une méthode statique ne peut pas accéder ni modifier l'état de la classe.
  • Il est présent dans une classe car il est logique que la méthode soit présente en classe.

Méthode de classe vs méthode statique

  • Une méthode de classe prend cls en tant que premier paramètre, tandis qu'une méthode statique ne nécessite aucun paramètre spécifique.
  • Une méthode de classe peut accéder à ou modifier l'état de la classe alors qu'une méthode statique ne peut pas y accéder ou la modifier.
  • Nous utilisons @classmethod decorator en python pour créer une méthode de classe et nous utilisons @staticmethod decorator pour créer une méthode statique en python.

Quand utiliser quoi?

  • Nous utilisons généralement la méthode de classe pour créer des méthodes d'usine. Les méthodes d'usine renvoient un objet de classe (similaire à un constructeur) pour différents cas d'utilisation.
  • Nous utilisons généralement des méthodes statiques pour créer des fonctions utilitaires.

Comment définir une méthode de classe et une méthode statique?

Pour définir une méthode de classe en python, nous utilisons @classmethod decorator et pour définir une méthode statique, nous utilisons @staticmethod decorator.

Regardons un exemple pour comprendre la différence entre les deux. Disons que nous voulons créer une personne de classe. Maintenant, python ne supporte pas la surcharge de méthodes comme C ++ ou Java, nous utilisons donc des méthodes de classe pour créer des méthodes de fabrique. Dans l'exemple ci-dessous, nous utilisons une méthode de classe pour créer un objet Personne à partir de l'année de naissance.

Comme expliqué ci-dessus, nous utilisons des méthodes statiques pour créer des fonctions utilitaires. Dans l'exemple ci-dessous, nous utilisons une méthode statique pour vérifier si une personne est adulte ou non.

la mise en oeuvre

21
21
True

Sortie

>>> class Klaus:
        @classmethod
        def classmthd(*args):
            return args

        @staticmethod
        def staticmthd(*args):
            return args

# 1. Call classmethod without any arg
>>> Klaus.classmthd()  
(__main__.Klaus,)  # the class gets passed as the first argument

# 2. Call classmethod with 1 arg
>>> Klaus.classmthd('chumma')
(__main__.Klaus, 'chumma')

# 3. Call staticmethod without any arg
>>> Klaus.staticmthd()  
()

# 4. Call staticmethod with 1 arg
>>> Klaus.staticmthd('chumma')
('chumma',)

Reference


Je vais essayer d'expliquer la différence fondamentale à l'aide d'un exemple.

class A(object):
    x = 0

    def say_hi(self):
        pass

    @staticmethod
    def say_hi_static():
        pass

    @classmethod
    def say_hi_class(cls):
        pass

    def run_self(self):
        self.x += 1
        print self.x # outputs 1
        self.say_hi()
        self.say_hi_static()
        self.say_hi_class()

    @staticmethod
    def run_static():
        print A.x  # outputs 0
        # A.say_hi() #  wrong
        A.say_hi_static()
        A.say_hi_class()

    @classmethod
    def run_class(cls):
        print cls.x # outputs 0
        # cls.say_hi() #  wrong
        cls.say_hi_static()
        cls.say_hi_class()

1 - on peut appeler directement des méthodes statiques et de classe sans initialiser

# A.run_self() #  wrong
A.run_static()
A.run_class()

2- La méthode statique ne peut pas appeler la méthode self mais peut appeler d'autres méthodes statiques et méthodes de classe

3- La méthode statique appartient à la classe et n'utilisera pas d'objet du tout.

4- Les méthodes de classe ne sont pas liées à un objet mais à une classe.


@decorators ont été ajoutés à python 2.4 Si vous utilisez python <2.4, vous pouvez utiliser les fonctions classmethod () et staticmethod ().

Par exemple, si vous souhaitez créer une méthode fabrique (une fonction renvoyant une instance d'une implémentation différente d'une classe en fonction de l'argument qu'elle obtient), vous pouvez effectuer les opérations suivantes:

class Cluster(object):

    def _is_cluster_for(cls, name):
        """
        see if this class is the cluster with this name
        this is a classmethod
        """ 
        return cls.__name__ == name
    _is_cluster_for = classmethod(_is_cluster_for)

    #static method
    def getCluster(name):
        """
        static factory method, should be in Cluster class
        returns a cluster object for the given name
        """
        for cls in Cluster.__subclasses__():
            if cls._is_cluster_for(name):
                return cls()
    getCluster = staticmethod(getCluster)

Notez également qu'il s'agit d'un bon exemple d'utilisation d'une méthode de classe et d'une méthode statique. La méthode statique appartient clairement à la classe car elle utilise la classe Cluster en interne. La méthode de classe n'a besoin que d'informations sur la classe et pas d'instance de l'objet.

Un autre avantage de faire de la méthode _is_cluster_for une classe est une méthode permettant à une sous-classe de modifier son implémentation, peut-être parce qu'elle est générique et qu'elle peut gérer plus d'un type de cluster. Le simple fait de vérifier le nom de la classe ne serait donc pas suffisant.


J'ai commencé à apprendre le langage de programmation avec C ++, puis Java, puis Python. Cette question m'a donc beaucoup dérangé jusqu'à ce que je comprenne l'utilisation simple de chacun.

Méthode de classe: contrairement à Java et C ++, Python ne surcharge pas le constructeur. Et pour y parvenir, vous pouvez utiliser classmethod . L'exemple suivant expliquera ceci

Considérons que nous avons une classe Person qui prend deux arguments last_name et last_name et crée l'instance de Person.

class Person(object):

    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

Maintenant, si l'exigence vient où vous devez créer une classe en utilisant un seul nom, juste un first_name , vous ne pouvez pas faire quelque chose comme ceci en python.

Cela vous donnera une erreur lorsque vous essayez de créer un objet (instance).

class Person(object):

    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

    def __init__(self, first_name):
        self.first_name = first_name

Cependant, vous pouvez obtenir la même chose en utilisant @classmethod comme mentionné ci-dessous

class Person(object):

    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

    @classmethod
    def get_person(cls, first_name):
        return cls(first_name, "")

Méthode statique : Ceci est assez simple, il n'est pas lié à une instance ou à une classe et vous pouvez simplement appeler cela en utilisant le nom de la classe.

Supposons donc que, dans l'exemple ci-dessus, vous avez besoin d'une validation dont le nom doit pas dépasser 20 caractères. Vous pouvez simplement le faire.

@staticmethod  
def validate_name(name):
    return len(name) <= 20

et vous pouvez simplement appeler en utilisant Nom de la classe

Person.validate_name("Gaurang Shah")

Peut-être qu'un exemple de code aidera: Notez la différence entre les signatures d'appel de foo , class_foo et static_foo :

class A(object):
    def foo(self,x):
        print "executing foo(%s,%s)"%(self,x)

    @classmethod
    def class_foo(cls,x):
        print "executing class_foo(%s,%s)"%(cls,x)

    @staticmethod
    def static_foo(x):
        print "executing static_foo(%s)"%x    

a=A()

Ci-dessous, la manière habituelle pour une instance d'objet d'appeler une méthode. L'instance d'objet, a , est implicitement passée en tant que premier argument.

a.foo(1)
# executing foo(<__main__.A object at 0xb7dbef0c>,1)

Avec classmethods , la classe de l'instance d'objet est implicitement passée en tant que premier argument au lieu de self .

a.class_foo(1)
# executing class_foo(<class '__main__.A'>,1)

Vous pouvez également appeler class_foo utilisant la classe. En fait, si vous définissez quelque chose comme étant une méthode de classe, c'est probablement parce que vous avez l'intention de l'appeler depuis la classe plutôt que depuis une instance de classe. A.foo(1) aurait généré une erreur TypeError, mais A.class_foo(1) fonctionne parfaitement:

A.class_foo(1)
# executing class_foo(<class '__main__.A'>,1)

Une utilisation que les utilisateurs ont trouvée pour les méthodes de classe consiste à créer des constructeurs alternatifs héritables .

Avec staticmethods , ni self (l'instance de l'objet) ni cls (la classe) ne sont implicitement passés en tant que premier argument. Ils se comportent comme des fonctions simples, sauf que vous pouvez les appeler à partir d'une instance ou de la classe:

a.static_foo(1)
# executing static_foo(1)

A.static_foo('hi')
# executing static_foo(hi)

Staticmethods sont utilisés pour grouper des fonctions qui ont une connexion logique avec une classe à la classe.

foo n'est qu'une fonction, mais lorsque vous appelez a.foo vous n'obtenez pas seulement la fonction, vous obtenez une version "partiellement appliquée" de la fonction, l'instance de l'objet étant liée comme premier argument de la fonction. foo attend 2 arguments, alors que a.foo n'attend qu'un argument.

a est lié à foo . C'est ce que l'on entend par le terme "lié" ci-dessous:

print(a.foo)
# <bound method A.foo of <__main__.A object at 0xb7d52f0c>>

Avec a.class_foo , a n'est pas lié à class_foo , mais la classe A est liée à class_foo .

print(a.class_foo)
# <bound method type.class_foo of <class '__main__.A'>>

Ici, avec une méthode static, même s’il s’agit d’une méthode, a.static_foo ne fait que a.static_foo une bonne fonction ole sans argument lié. static_foo attend 1 argument et a.static_foo attend également 1 argument.

print(a.static_foo)
# <function static_foo at 0xb7d479cc>

Et bien sûr, la même chose se produit lorsque vous appelez static_foo avec la classe A

print(A.static_foo)
# <function static_foo at 0xb7d479cc>

@classmethod crée une méthode dont le premier argument est la classe à partir de laquelle elle est appelée (plutôt que l'instance de la classe). @staticmethod n'a pas d'argument implicite.


Here un court article sur cette question

La fonction @staticmethod n'est rien d'autre qu'une fonction définie dans une classe. Il est appelable sans instancier d'abord la classe. Sa définition est immuable par héritage.

La fonction @classmethod peut également être appelée sans instancier la classe, mais sa définition suit la classe Sub, et non la classe Parent, via l'héritage. En effet, le premier argument de la fonction @classmethod doit toujours être cls (classe).


Analysez @staticmethod fournissant littéralement différentes idées.

Une méthode normale d'une classe est une méthode dynamique implicite qui prend l'instance comme premier argument.
En revanche, une méthode statique ne prend pas l'instance comme premier argument, elle est donc appelée "statique" .

Une méthode statique est en effet une fonction aussi normale que celle utilisée en dehors d'une définition de classe.
Il est heureusement regroupé dans la classe afin de rester plus près de l'endroit où il est appliqué ou vous pouvez faire défiler pour le trouver.


Je pense qu'une meilleure question est "Quand utiliseriez-vous @classmethod vs @staticmethod?"

@classmethod vous permet d'accéder facilement aux membres privés associés à la définition de classe. c'est un excellent moyen de faire des singletons, ou des classes d'usine qui contrôlent le nombre d'instances des objets créés.

@staticmethod fournit des gains de performance marginaux, mais je n'ai pas encore vu l'utilisation productive d'une méthode statique dans une classe qui ne pourrait pas être réalisée en tant que fonction autonome en dehors de la classe.


Permettez-moi de dire la similitude entre une méthode décorée avec @classmethod vs @staticmethod en premier.

Similarité: les deux peuvent être appelés sur la classe elle-même, plutôt que simplement sur l' instance de la classe. Donc, les deux sont en un sens les méthodes de Class .

Différence: une méthode de classe recevra la classe elle-même comme premier argument, contrairement à une méthode statique.

Ainsi, une méthode statique n’est, dans un sens, pas liée à la classe elle-même et reste suspendue simplement parce qu’elle peut avoir une fonctionnalité connexe.

class C(object):
    @classmethod
    def fun(cls, arg1, arg2, ...):
       ....

fun: function that needs to be converted into a class method
returns: a class method for function.

Ma contribution montre la différence entre @classmethod, @staticmethodet les méthodes d’instance, y compris la manière dont une instance peut appeler indirectement a @staticmethod. Mais au lieu d'appeler indirectement un @staticmethoddepuis une instance, le rendre privé peut être plus "pythonique". Obtenir quelque chose d'une méthode privée n'est pas démontré ici mais c'est fondamentalement le même concept.

#!python3

from os import system
system('cls')
# %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %

class DemoClass(object):
    # instance methods need a class instance and
    # can access the instance through 'self'
    def instance_method_1(self):
        return 'called from inside the instance_method_1()'

    def instance_method_2(self):
        # an instance outside the class indirectly calls the static_method
        return self.static_method() + ' via instance_method_2()'

    # class methods don't need a class instance, they can't access the
    # instance (self) but they have access to the class itself via 'cls'
    @classmethod
    def class_method(cls):
        return 'called from inside the class_method()'

    # static methods don't have access to 'cls' or 'self', they work like
    # regular functions but belong to the class' namespace
    @staticmethod
    def static_method():
        return 'called from inside the static_method()'
# %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %

# works even if the class hasn't been instantiated
print(DemoClass.class_method() + '\n')
''' called from inside the class_method() '''

# works even if the class hasn't been instantiated
print(DemoClass.static_method() + '\n')
''' called from inside the static_method() '''
# %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %

# >>>>> all methods types can be called on a class instance <<<<<
# instantiate the class
democlassObj = DemoClass()

# call instance_method_1()
print(democlassObj.instance_method_1() + '\n')
''' called from inside the instance_method_1() '''

# # indirectly call static_method through instance_method_2(), there's really no use
# for this since a @staticmethod can be called whether the class has been
# instantiated or not
print(democlassObj.instance_method_2() + '\n')
''' called from inside the static_method() via instance_method_2() '''

# call class_method()
print(democlassObj.class_method() + '\n')
'''  called from inside the class_method() '''

# call static_method()
print(democlassObj.static_method())
''' called from inside the static_method() '''

"""
# whether the class is instantiated or not, this doesn't work
print(DemoClass.instance_method_1() + '\n')
'''
TypeError: TypeError: unbound method instancemethod() must be called with
DemoClass instance as first argument (got nothing instead)
'''
"""

Documents officiels en python:

@classmethod

Une méthode de classe reçoit la classe en tant que premier argument implicite, tout comme une méthode d'instance reçoit l'instance. Pour déclarer une méthode de classe, utilisez cet idiome:

class C:
    @classmethod
    def f(cls, arg1, arg2, ...): ... 

La forme @classmethod est un decorator fonctions - voir la description des définitions de fonctions dans Définitions de fonctions pour plus de détails.

Il peut être appelé soit sur la classe (telle que Cf() ), soit sur une instance (telle que C().f() ). L'instance est ignorée à l'exception de sa classe. Si une méthode de classe est appelée pour une classe dérivée, l'objet de classe dérivée est passé en tant que premier argument implicite.

Les méthodes de classe sont différentes des méthodes statiques C ++ ou Java. Si vous voulez ceux-ci, voyez staticmethod() dans cette section.

@staticmethod

Une méthode statique ne reçoit pas de premier argument implicite. Pour déclarer une méthode statique, utilisez cet idiome:

class C:
    @staticmethod
    def f(arg1, arg2, ...): ... 

La forme @staticmethod est un decorator fonction - voir la description des définitions de fonction dans Définitions de fonction pour plus de détails.

Il peut être appelé soit sur la classe (telle que Cf() ), soit sur une instance (telle que C().f() ). L'instance est ignorée à l'exception de sa classe.

Les méthodes statiques en Python sont similaires à celles trouvées en Java ou en C ++. Pour un concept plus avancé, consultez classmethod() dans cette section.


Quelle est la différence entre @staticmethod et @classmethod en Python?

Vous avez peut-être vu du code Python comme ce pseudocode, qui illustre les signatures des différents types de méthodes et fournit une docstring pour expliquer chacun:

class Foo(object):

    def a_normal_instance_method(self, arg_1, kwarg_2=None):
        '''
        Return a value that is a function of the instance with its
        attributes, and other arguments such as arg_1 and kwarg2
        '''

    @staticmethod
    def a_static_method(arg_0):
        '''
        Return a value that is a function of arg_0. It does not know the 
        instance or class it is called from.
        '''

    @classmethod
    def a_class_method(cls, arg1):
        '''
        Return a value that is a function of the class and other arguments.
        respects subclassing, it is called with the class it is called from.
        '''

La méthode d'instance normale

Je vais d'abord expliquer une a_normal_instance_method . Ceci s'appelle précisément une " méthode d'instance ". Lorsqu'une méthode d'instance est utilisée, elle est utilisée comme une fonction partielle (par opposition à une fonction globale définie pour toutes les valeurs affichées dans le code source), c'est-à-dire que, lorsqu'il est utilisé, le premier des arguments est prédéfini en tant qu'instance du paramètre. objet, avec tous ses attributs donnés. L'instance de l'objet y est liée et doit être appelée à partir d'une instance de l'objet. En règle générale, il accédera à divers attributs de l'instance.

Par exemple, ceci est une instance d'une chaîne:

', '

si nous utilisons la méthode d'instance, join sur cette chaîne, pour joindre un autre itérable, il s'agit bien évidemment d'une fonction de l'instance, en plus d'être une fonction de la liste itérable, ['a', 'b', 'c'] :

>>> ', '.join(['a', 'b', 'c'])
'a, b, c'

Méthodes liées

Les méthodes d'instance peuvent être liées via une recherche en pointillé pour une utilisation ultérieure.

Par exemple, cela lie la méthode str.join à l'instance ':' :

>>> join_with_colons = ':'.join 

Et plus tard, nous pouvons l’utiliser comme une fonction à laquelle le premier argument est déjà lié. De cette façon, cela fonctionne comme une fonction partielle sur l'instance:

>>> join_with_colons('abcde')
'a:b:c:d:e'
>>> join_with_colons(['FF', 'FF', 'FF', 'FF', 'FF', 'FF'])
'FF:FF:FF:FF:FF:FF'

Méthode statique

La méthode statique ne prend pas l'instance en argument.

C'est très similaire à une fonction de niveau module.

Cependant, une fonction de niveau module doit résider dans le module et être spécialement importée vers d'autres emplacements où elle est utilisée.

Cependant, s'il est attaché à l'objet, il le suivra facilement lors de l'importation et de l'héritage.

str.maketrans est un exemple de méthode statique. Il est déplacé du module string de Python 3. Il rend une table de traduction appropriée à la consommation par str.translate . Cela semble plutôt ridicule quand on l'utilise à partir d'une instance d'une chaîne, comme illustré ci-dessous, mais importer la fonction à partir du module string est plutôt maladroit, et il est agréable de pouvoir l'appeler depuis la classe, comme dans str.maketrans

# demonstrate same function whether called from instance or not:
>>> ', '.maketrans('ABC', 'abc')
{65: 97, 66: 98, 67: 99}
>>> str.maketrans('ABC', 'abc')
{65: 97, 66: 98, 67: 99}

En python 2, vous devez importer cette fonction à partir du module de chaîne de moins en moins utile:

>>> import string
>>> 'ABCDEFG'.translate(string.maketrans('ABC', 'abc'))
'abcDEFG'

Méthode de classe

Une méthode de classe est similaire à une méthode d'instance en ce qu'elle prend un premier argument implicite, mais au lieu de prendre l'instance, elle prend la classe. Souvent, ils sont utilisés en tant que constructeurs alternatifs pour un meilleur usage sémantique et cela prend en charge l'héritage.

L'exemple le plus canonique d'une méthode de classe intégrée est dict.fromkeys . Il est utilisé en tant que constructeur alternatif de dict (convient bien lorsque vous connaissez vos clés et souhaitez une valeur par défaut pour celles-ci.)

>>> dict.fromkeys(['a', 'b', 'c'])
{'c': None, 'b': None, 'a': None}

Lorsque nous sous-classe dict, nous pouvons utiliser le même constructeur, ce qui crée une instance de la sous-classe.

>>> class MyDict(dict): 'A dict subclass, use to demo classmethods'
>>> md = MyDict.fromkeys(['a', 'b', 'c'])
>>> md
{'a': None, 'c': None, 'b': None}
>>> type(md)
<class '__main__.MyDict'>

Voir le code source de pandas pour d'autres exemples similaires de constructeurs alternatifs, et voir aussi la documentation officielle de Python sur classmethod et staticmethod .


@classmethod: peut être utilisé pour créer un accès global partagé à toutes les instances créées de cette classe ... comme la mise à jour d'un enregistrement par plusieurs utilisateurs .... )

Méthode @static: n'a rien à voir avec la classe ou l'instance associée à ... mais pour des raisons de lisibilité, vous pouvez utiliser la méthode statique


En bref, @classmehtod transforme une méthode normale en méthode usine.

Explorons-le avec un exemple:

class PythonBook:
    def __init__(self, name, author):
        self.name = name
        self.author = author
    def __repr__(self):
        return f'Book: {self.name}, Author: {self.author}'

Sans un @ classmethod, vous devez travailler à créer des instances une par une et ils sont scartés.

book1 = PythonBook('Learning Python', 'Mark Lutz')
In [20]: book1
Out[20]: Book: Learning Python, Author: Mark Lutz
book2 = PythonBook('Python Think', 'Allen B Dowey')
In [22]: book2
Out[22]: Book: Python Think, Author: Allen B Dowey

Comme par exemple avec @classmethod

class PythonBook:
    def __init__(self, name, author):
        self.name = name
        self.author = author
    def __repr__(self):
        return f'Book: {self.name}, Author: {self.author}'
    @classmethod
    def book1(cls):
        return cls('Learning Python', 'Mark Lutz')
    @classmethod
    def book2(cls):
        return cls('Python Think', 'Allen B Dowey')

Essaye-le:

In [31]: PythonBook.book1()
Out[31]: Book: Learning Python, Author: Mark Lutz
In [32]: PythonBook.book2()
Out[32]: Book: Python Think, Author: Allen B Dowey

Voir? Les instances sont créées avec succès dans une définition de classe et sont collectées ensemble.

En conclusion, le décorateur @classmethod convertit une méthode conventionnelle en méthode usine. Utiliser classmethods permet d'ajouter autant de constructeurs que nécessaire.







python oop methods python-decorators