J'ai rencontré une erreur de méthode non liée en python avec le code
import random
class Sample(object):
'''This class defines various methods related to the sample'''
def drawSample(samplesize,List):
sample=random.sample(List,samplesize)
return sample
Choices=range(100)
print Sample.drawSample(5,Choices)
Après avoir lu de nombreux articles utiles ici, j'ai compris comment je pourrais ajouter @staticmethod
ci-dessus pour que le code fonctionne. Je suis un novice en python. Quelqu'un peut-il expliquer pourquoi on voudrait définir des méthodes statiques? Ou pourquoi toutes les méthodes ne sont-elles pas définies comme des méthodes statiques?
python
oop
static-methods
Curieux2learn
la source
la source
Réponses:
Les méthodes statiques ont une utilisation limitée, car elles n'ont pas accès aux attributs d'une instance d'une classe (comme le fait une méthode régulière), et elles n'ont pas accès aux attributs de la classe elle-même (comme le fait une méthode de classe ).
Ils ne sont donc pas utiles pour les méthodes quotidiennes.
Cependant, ils peuvent être utiles pour regrouper une fonction utilitaire avec une classe - par exemple une simple conversion d'un type à un autre - qui n'a pas besoin d'accéder à des informations en dehors des paramètres fournis (et peut-être des attributs globaux au module. )
Ils pourraient être mis en dehors de la classe, mais les regrouper à l'intérieur de la classe peut avoir un sens là où ils ne sont applicables que là-bas.
Vous pouvez également référencer la méthode via une instance ou la classe, plutôt que le nom du module, ce qui peut aider le lecteur à comprendre à quelle instance la méthode est liée.
la source
Locale
classe, dont les instances seront locales (duh). UnegetAvailableLocales()
méthode serait un bel exemple de méthode statique d'une telle classe: elle appartient clairement à la classe Locale, tout en n'appartenant clairement à aucune instance particulière.class_name.attribute
, mais pascls.attribute
ouself.attribute
. Ceci est vrai pour les attributs "publics". Par convention, vous ne devriez pas accéder aux attributs masqués par un trait de soulignement, ou aux noms mutilés avec deux traits de soulignement, de cette façon. Cela signifie également que votre code sera plus fragile lorsque les attributs changeront de place dans la hiérarchie d'héritage.Consultez cet article pour une explication détaillée.
TL; DR
1.Il élimine l'utilisation de l'
self
argument.Cela réduit l'utilisation de la mémoire car Python n'a pas besoin d'instancier une méthode liée pour chaque objet instiantié:
>>>RandomClass().regular_method is RandomClass().regular_method False >>>RandomClass().static_method is RandomClass().static_method True >>>RandomClass.static_method is RandomClass().static_method True
3. Il améliore la lisibilité du code, ce qui signifie que la méthode ne dépend pas de l'état de l'objet lui-même.
4.Il permet le remplacement de méthode en ce que si la méthode était définie au niveau du module (c'est-à-dire en dehors de la classe), une sous-classe ne serait pas en mesure de remplacer cette méthode.
la source
Ce n'est pas tout à fait au point de votre question réelle, mais puisque vous avez dit que vous êtes un débutant en python, cela sera peut-être utile, et personne d'autre ne l'a dit explicitement.
Je n'aurais jamais corrigé le code ci-dessus en faisant de la méthode une méthode statique. J'aurais soit abandonné la classe et juste écrit une fonction:
def drawSample(samplesize,List): sample=random.sample(List,samplesize) return sample Choices=range(100) print drawSample(5,Choices)
Si vous avez de nombreuses fonctions associées, vous pouvez les regrouper dans un module - c'est-à-dire les mettre toutes dans le même fichier, nommé
sample.py
par exemple; puisimport sample Choices=range(100) print sample.drawSample(5,Choices)
Ou j'aurais ajouté une
__init__
méthode à la classe et créé une instance qui avait des méthodes utiles:class Sample(object): '''This class defines various methods related to the sample''' def __init__(self, thelist): self.list = thelist def draw_sample(self, samplesize): sample=random.sample(self.list,samplesize) return sample choices=Sample(range(100)) print choices.draw_sample(5)
(J'ai également modifié les conventions de casse dans l'exemple ci-dessus pour qu'elles correspondent au style recommandé par PEP 8.)
L'un des avantages de Python est qu'il ne vous oblige pas à utiliser des classes pour tout. Vous ne pouvez les utiliser que lorsqu'il y a des données ou un état qui doivent être associés aux méthodes, ce à quoi servent les classes. Sinon, vous pouvez utiliser des fonctions, à quoi servent les fonctions.
la source
Pourquoi voudrait-on définir des méthodes statiques ?
Supposons que nous ayons un
class
appeléMath
alorspersonne ne voudra créer un objet
class Math
et ensuite invoquer des méthodes comme
ceil
etfloor
etfabs
sur lui.Alors nous les fabriquons
static
.Par exemple faire
>> Math.floor(3.14)
est bien mieux que
>> mymath = Math() >> mymath.floor(3.14)
Ils sont donc utiles d'une certaine manière. Vous n'avez pas besoin de créer une instance d'une classe pour les utiliser.
Pourquoi toutes les méthodes ne sont-elles pas définies comme des méthodes statiques ?
Ils n'ont pas accès aux variables d'instance.
class Foo(object): def __init__(self): self.bar = 'bar' def too(self): print self.bar @staticmethod def foo(): print self.bar Foo().too() # works Foo.foo() # doesn't work
C'est pourquoi nous ne rendons pas toutes les méthodes statiques.
la source
Math
. C'est pourquoi j'ai capitaliséM
.Math
soyez une classe en premier lieu, un module conviendrait mieux. Essayez de trouver un exemple de classe qui a du sens en tant que classe, pas une classe dont "personne ne voudra créer un objet" .Lorsque vous appelez un objet fonction à partir d'une instance d'objet, il devient une «méthode liée» et obtient que l'objet d'instance lui-même est passé en tant que premier argument.
Lorsque vous appelez un
classmethod
objet (qui encapsule un objet fonction) sur une instance d'objet, la classe de l'objet instance est transmise comme premier argument.Lorsque vous appelez un
staticmethod
objet (qui encapsule un objet fonction), aucun premier argument implicite n'est utilisé.class Foo(object): def bar(*args): print args @classmethod def baaz(*args): print args @staticmethod def quux(*args): print args >>> foo = Foo() >>> Foo.bar(1,2,3) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unbound method bar() must be called with Foo instance as first argument (got int instance instead) >>> Foo.baaz(1,2,3) (<class 'Foo'>, 1, 2, 3) >>> Foo.quux(1,2,3) (1, 2, 3) >>> foo.bar(1,2,3) (<Foo object at 0x1004a4510>, 1, 2, 3) >>> foo.baaz(1,2,3) (<class 'Foo'>, 1, 2, 3) >>> foo.quux(1,2,3) (1, 2, 3)
la source
Les méthodes statiques sont excellentes car vous n'avez pas à déclarer une instance de l'objet auquel appartient la méthode.
Le site de python a une excellente documentation sur les méthodes statiques ici:
http://docs.python.org/library/functions.html#staticmethod
la source
Les alternatives à une
staticmethod
sont:classmethod
,instancemethod
etfunction
. Si vous ne savez pas ce que c'est, faites défiler jusqu'à la dernière section. Si astaticmethod
est meilleur que l'une de ces alternatives, cela dépend de l'objectif dans lequel il est écrit.avantages de la méthode statique Python
staticmethod
vaut mieux queclassmethod
ouinstancemethod
. De cette façon, il est clair (d'après le@staticmethod
décorateur) que l'état de la classe et de l'instance n'est ni lu ni modifié. Cependant, l'utilisation d'unfunction
rend cette distinction encore plus claire (voir les inconvénients).staticmethod
est la même que celle de aclassmethod
ouinstancemethod
, à savoir<instance>.<method>(<arguments>)
. Par conséquent, il peut facilement être remplacé par l'un des trois si cela est nécessaire plus tard ou dans une classe dérivée. Vous ne pouvez pas faire ça avec un simplefunction
.staticmethod
peut être utilisé à la place de afunction
pour indiquer clairement qu'il appartient subjectivement à une classe et pour éviter les conflits d'espace de noms.inconvénients de la méthode statique Python
staticmethod
est la même que celle de aclassmethod
ouinstancemethod
. Cela masque le fait que lestaticmethod
ne lit ni ne modifie réellement aucune information d'objet. Cela rend le code plus difficile à lire. Pourquoi ne pas simplement utiliser unfunction
?staticmethod
est difficile à réutiliser si jamais vous avez besoin de l'appeler depuis l'extérieur de la classe / instance où il a été défini. S'il existe un potentiel de réutilisation, afunction
est le meilleur choix.staticmethod
est rarement utilisé, donc les personnes qui lisent du code qui en contient un peuvent prendre un peu plus de temps à le lire.alternatives à une méthode statique en Python
Pour discuter des avantages du
staticmethod
, nous devons savoir quelles sont les alternatives et en quoi elles diffèrent les unes des autres.staticmethod
appartient à une classe mais ne peut accéder ni modifier les informations d'instance ou de classe.Il existe trois alternatives:
classmethod
a accès à la classe de l'appelant.instancemethod
a accès à l'instance de l'appelant et à sa classe.function
n'a rien à voir avec les cours. C'est le plus proche en capacité dustaticmethod
.Voici à quoi cela ressemble dans le code:
# function # has nothing to do with a class def make_cat_noise(asker_name): print('Hi %s, mieets mieets!' % asker_name) # Yey, we can make cat noises before we've even defined what a cat is! make_cat_noise('JOey') # just a function class Cat: number_of_legs = 4 # special instance method __init__ def __init__(self, name): self.name = name # instancemethod # the instance (e.g. Cat('Kitty')) is passed as the first method argument def tell_me_about_this_animal(self, asker_name): print('Hi %s, This cat has %d legs and is called %s' % (asker_name, self.number_of_legs, self.name)) # classmethod # the class (e.g. Cat) is passed as the first method argument # by convention we call that argument cls @classmethod def tell_me_about_cats(cls, asker_name): print("Hi %s, cats have %d legs." % (asker_name, cls.number_of_legs)) # cls.name # AttributeError because only the instance has .name # self.name # NameError because self isn't defined in this namespace # staticmethod # no information about the class or the instance is passed to the method @staticmethod def make_noise(asker_name): print('Hi %s, meooow!' % asker_name) # class and instance are not accessible from here # one more time for fun! make_cat_noise('JOey') # just a function # We just need the class to call a classmethod or staticmethod: Cat.make_noise('JOey') # staticmethod Cat.tell_me_about_cats('JOey') # classmethod # Cat.tell_me_about_this_animal('JOey') # instancemethod -> TypeError # With an instance we can use instancemethod, classmethod or staticmethod mycat = Cat('Kitty') # mycat is an instance of the class Cat mycat.make_noise('JOey') # staticmethod mycat.tell_me_about_cats('JOey') # classmethod mycat.tell_me_about_this_animal('JOey') # instancemethod
la source
Parce que les fonctions d'espacement de noms sont agréables (comme cela a été souligné précédemment):
Lorsque je veux être explicite sur les méthodes qui ne changent pas l'état de l'objet, j'utilise des méthodes statiques. Cela décourage les membres de mon équipe de commencer à modifier les attributs de l'objet dans ces méthodes.
Quand je refactorise du code vraiment pourri, je commence par essayer de créer autant de méthodes
@staticmethod
que possible. Cela me permet ensuite d'extraire ces méthodes dans une classe - bien que je sois d'accord, c'est rarement quelque chose que j'utilise, cela m'a été utile à quelques reprises.la source
À mon avis, il n'y a pas un seul avantage en termes de performances à utiliser
@staticmethod
s par rapport à la simple définition de la fonction en dehors de et distincte de la classe dont elle serait autrement une@staticmethod
.La seule chose que je dirais justifie leur existence, c'est la commodité. Les méthodes statiques sont courantes dans d'autres langages de programmation populaires, alors pourquoi pas python? Si vous souhaitez créer une fonction avec un comportement qui est très étroitement associé à la classe pour laquelle vous la créez mais qu'elle n'accède pas / ne modifie pas réellement les données internes d'une instance de la classe d'une manière qui justifie sa conceptualisation méthode de cette classe puis gifler un
@staticmethod
au dessus et toute personne lisant votre code en apprendra immédiatement beaucoup sur la nature de la méthode et sa relation avec la classe.Une chose que j'aime parfois faire est de placer des fonctionnalités que ma classe utilise beaucoup en interne dans des
@staticmethod
s privés . De cette façon, je n'encombre pas l'API exposée par mon module avec des méthodes que personne qui utilise mon module n'aurait jamais besoin de voir et encore moins d'utiliser.la source
Les méthodes statiques n'ont presque aucune raison d'être en Python. Vous utilisez des méthodes d'instance ou des méthodes de classe.
def method(self, args): self.member = something @classmethod def method(cls, args): cls.member = something @staticmethod def method(args): MyClass.member = something # The above isn't really working # if you have a subclass
la source
staticmethod
ni aucune explication de ce qu'est unclassmethod
ou pourquoi et en quoi il est "meilleur" que les statiques.staticmethod
dans les documents pour soutenir votre affirmation selon laquelle c'est cruel, ou l'affirmation de Georg quiclassmethod
devrait être utilisée à la place).