1846 votes

Méthodes statiques en Python ?

Est-il possible d’avoir des méthodes statiques en Python, donc je peux les appeler sans initialiser une classe, comme :

2135voto

dbr Points 66401

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 (comme C().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é.

237voto

richthepanda Points 943

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)

85voto

Paolo Bergantino Points 199336

Oui, Découvrez le décorateur de staticmethod :

12voto

Filip Dupanović Points 10071

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X