Est-il possible d’avoir des méthodes statiques en Python, donc je peux les appeler sans initialiser une classe, comme :
Réponses
Trop de publicités?Yep, à l'aide de la staticmethod décorateur
class MyClass(object):
@staticmethod
def the_static_method(x):
print x
MyClass.the_static_method(2) # outputs 2
Note qu'un code peut utiliser l'ancienne méthode de définition d'une méthode statique, à l'aide de staticmethod
comme une fonction plutôt qu'un décorateur. Cela ne devrait être utilisé que si vous avez à soutenir les anciennes versions de Python (2.2 et 2.3)
class MyClass(object):
def the_static_method(x):
print x
the_static_method = staticmethod(the_static_method)
MyClass.the_static_method(2) # outputs 2
C'est tout à fait identique à celui du premier exemple (à l'aide d' @staticmethod
), mais pas à l'aide de la belle décorateur syntaxe
Enfin, servez - staticmethod
avec parcimonie! Il y a très peu de situations où la statique méthodes sont nécessaires en Python, et je les ai vu plusieurs fois où un des "top-niveau" de la fonction aurait été plus clair.
Docs:
Une méthode statique ne reçoit pas un implicite premier argument. Pour déclarer une méthode statique, utiliser ce langage:
class C: @staticmethod def f(arg1, arg2, ...): ...
@Staticmethod forme est une fonction de décorateur – voir la description de la fonction des définitions en Fonction des définitions pour plus de détails.
Il peut être appelé soit sur la classe (comme
C.f()
) ou sur une instance (commeC().f()
). L'instance est ignorée à l'exception de sa classe.Méthodes statiques en Python sont semblables à ceux trouvés en Java ou en C++. Pour les plus avancés, concept, voir classmethod().
Pour plus d'informations sur les méthodes statiques, consultez la documentation sur le type standard de hiérarchie dans La norme de la hiérarchie des types.
Nouveau dans la version 2.2.
Modifié dans la version 2.4: Fonction décorateur syntaxe ajouté.
Je pense que Steven est effectivement droit. Pour répondre à la question d'origine, puis, afin de mettre en place une méthode d'une classe, il suffit de supposer que le premier argument est ne va pas être une instance d'appel, puis assurez-vous que vous avez seulement l'appel à la méthode de la classe. Par exemple:
class Dog:
count = 0 # this is a class variable
dogs = [] # this is a class variable
def __init__(self, name):
self.name = name #self.name is an instance variable
Dog.count += 1
Dog.dogs.append(name)
def bark(self, n): # this is an instance method
print("{} says: {}".format(self.name, "woof! " * n))
def rollCall(n): #this is implicitly a class method (see comments below)
print("There are {} dogs.".format(Dog.count))
if n >= len(Dog.dogs) or n < 0:
print("They are:")
for dog in Dog.dogs:
print(" {}".format(dog))
else:
print("The dog indexed at {} is {}.".format(n, Dog.dogs[n]))
fido = Dog("Fido")
fido.bark(3)
Dog.rollCall(-1)
rex = Dog("Rex")
Dog.rollCall(0)
Dans ce code, le "par appel nominal" méthode suppose que le premier argument n'est pas une instance (comme elle le serait si elle était appelée par une instance au lieu d'une classe). Aussi longtemps que "par appel nominal" est appelé à partir de la classe plutôt qu'à une instance, le code fonctionne bien. Si nous essayons de faire appel "par appel nominal" à partir d'une instance, par ex.:
rex.rollCall(-1)
cependant, il serait la cause d'une exception soulevée, car elle permettrait d'envoyer deux arguments: lui-même et de -1, et "par appel nominal" est défini à accepter un argument.
D'ailleurs, rex.vote à l'appel nominal() envoie le bon nombre d'arguments, mais aussi de provoquer une exception à être élevés parce que maintenant n serait représentant un Chien instance (c'est à dire, rex) lorsque la fonction s'attend à n être numérique.
C'est là que la décoration: Si nous précéder la "par appel nominal" la méthode avec
@staticmethod
puis, en indiquant expressément que la méthode est statique, on peut même l'appeler à partir d'une instance. Maintenant,
rex.rollCall(-1)
serait de travailler. L'insertion de @staticmethod avant une définition de la méthode, ensuite, s'arrête à une instance de l'envoi lui-même comme un argument.
Vous pouvez le vérifier en essayant le code suivant avec et sans le @staticmethod ligne en commentaire.
class Dog:
count = 0 # this is a class variable
dogs = [] # this is a class variable
def __init__(self, name):
self.name = name #self.name is an instance variable
Dog.count += 1
Dog.dogs.append(name)
def bark(self, n): # this is an instance method
print("{} says: {}".format(self.name, "woof! " * n))
@staticmethod
def rollCall(n):
print("There are {} dogs.".format(Dog.count))
if n >= len(Dog.dogs) or n < 0:
print("They are:")
for dog in Dog.dogs:
print(" {}".format(dog))
else:
print("The dog indexed at {} is {}.".format(n, Dog.dogs[n]))
fido = Dog("Fido")
fido.bark(3)
Dog.rollCall(-1)
rex = Dog("Rex")
Dog.rollCall(0)
rex.rollCall(-1)
Oui, Découvrez le décorateur de staticmethod :
Outre les particularités de la façon dont la méthode statique des objets se comportent, il ya un certain type de beauté que vous pouvez frapper avec eux quand il s'agit de l'organisation de votre code au niveau du module.
# garden.py
def trim(a):
pass
def strip(a):
pass
def bunch(a, b):
pass
def _foo(foo):
pass
class powertools(object):
"""
Provides much regarded gardening power tools.
"""
@staticmethod
def answer_to_the_ultimate_question_of_life_the_universe_and_everything():
return 42
@staticmethod
def random():
return 13
@staticmethod
def promise():
return True
def _bar(baz, quux):
pass
class _Dice(object):
pass
class _6d(_Dice):
pass
class _12d(_Dice):
pass
class _Smarter:
pass
class _MagicalPonies:
pass
class _Samurai:
pass
class Foo(_6d, _Samurai):
pass
class Bar(_12d, _Smarter, _MagicalPonies):
pass
# tests.py
import unittest
import garden
class GardenTests(unittest.TestCase):
pass
class PowertoolsTests(unittest.TestCase):
pass
class FooTests(unittest.TestCase):
pass
class BarTests(unittest.TestCase):
pass
# interactive.py
from garden import trim, bunch, Foo
f = trim(Foo())
bunch(f, Foo())
# my_garden.py
import garden
from garden import powertools
class _Cowboy(garden._Samurai):
def hit():
return powertools.promise() and powertools.random() or 0
class Foo(_Cowboy, garden.Foo):
pass
Il devient maintenant un peu plus intuitive et d'auto-documenter le contexte dans lequel certains composants sont conçus pour être utilisés et paternité idéalement pour la dénomination distincte des cas de test ainsi que d'avoir une approche simple pour combien de modules de test de la carte de modules en vertu de tests pour les puristes.
J'ai souvent trouver viable pour appliquer cette approche à l'organisation d'un projet de code d'utilitaire. Assez souvent, les gens immédiatement se précipiter et de créer un utils
forfait et jusqu'à la fin avec 9 modules dont un a 120 LOC et le reste sont de deux douzaines de LOC au mieux. Je préfère commencer avec ça et de le convertir en un paquet et de créer des modules pour les bêtes qui méritent vraiment eux:
# utils.py
class socket(object):
@staticmethod
def check_if_port_available(port):
pass
@staticmethod
def get_free_port(port)
pass
class image(object):
@staticmethod
def to_rgb(image):
pass
@staticmethod
def to_cmyk(image):
pass