Saltar al contenido

¿Métodos estáticos en Python? – Desbordamiento de pila

octubre 21, 2021
apple touch icon@2

Creo que Steven tiene razón. Entonces, para responder a la pregunta original, para configurar un método de clase, simplemente asuma que el primer argumento no será una instancia de llamada, y luego asegúrese de llamar al método solo desde la clase.

(Tenga en cuenta que esta respuesta se refiere a Python 3.x. En Python 2.x obtendrá un TypeError para llamar al método en la propia clase).

Por ejemplo:

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)

En este código, el método «rollCall» asume que el primer argumento no es una instancia (como sería si fuera llamado por una instancia en lugar de una clase). Siempre que se llame a «rollCall» desde la clase en lugar de una instancia, el código funcionará bien. Si intentamos llamar a «rollCall» desde una instancia, por ejemplo:

rex.rollCall(-1)

sin embargo, provocaría la aparición de una excepción porque enviaría dos argumentos: él mismo y -1, y «rollCall» solo está definido para aceptar un argumento.

Por cierto, rex.rollCall () enviaría el número correcto de argumentos, pero también provocaría una excepción porque ahora n representaría una instancia de Dog (es decir, rex) cuando la función espera que n sea numérico.

Aquí es donde entra la decoración: si precedemos al método «rollCall» con

@staticmethod

luego, al indicar explícitamente que el método es estático, incluso podemos llamarlo desde una instancia. Ahora,

rex.rollCall(-1)

trabajaría. La inserción de @staticmethod antes de la definición de un método, entonces, evita que una instancia se envíe a sí misma como un argumento.

Puede verificar esto probando el siguiente código con y sin la línea @staticmethod comentada.

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)
close