Вопрос-Ответ

Static methods in Python?

Статические методы в Python?

Могу ли я определить статический метод, который я могу вызывать непосредственно в экземпляре класса? например,

MyClass.the_static_method()
Переведено автоматически
Ответ 1

Да, используя staticmethod декоратор:

class MyClass(object):
@staticmethod
def the_static_method(x):
print(x)

MyClass.the_static_method(2) # outputs 2

Обратите внимание, что в некотором коде может использоваться старый метод определения статического метода, используя staticmethod как функцию, а не декоратор. Это следует использовать только в том случае, если вам необходимо поддерживать старые версии Python (2.2 и 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

Это полностью идентично первому примеру (с использованием @staticmethod), просто не используется приятный синтаксис декоратора.

Наконец, используйте staticmethod экономно! В Python очень мало ситуаций, когда статические методы необходимы, и я много раз видел, как они использовались, когда отдельная функция "верхнего уровня" была бы понятнее.


Следующее дословно приведено из документации::


Статический метод не получает неявный первый аргумент. Чтобы объявить статический метод, используйте эту идиому:


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

Форма @staticmethod является декоратором функции – смотрите Описание определений функций в разделе Определения функций для получения подробной информации.


Это может быть вызвано либо для класса (например, C.f()), либо для экземпляра (например, C().f()). Экземпляр игнорируется, за исключением его класса.


Статические методы в Python аналогичны методам, используемым в Java или C ++. Более подробную концепцию см. classmethod().


Для получения дополнительной информации о статических методах обратитесь к документации по стандартной иерархии типов в The standard type hierarchy.


Новое в версии 2.2.


Изменено в версии 2.4: добавлен синтаксис декоратора функций.


Ответ 2

Я думаю, что Стивен на самом деле прав. Чтобы ответить на исходный вопрос, тогда, чтобы настроить метод класса, просто предположите, что первый аргумент не будет вызывающим экземпляром, а затем убедитесь, что вы вызываете метод только из класса.

(Обратите внимание, что этот ответ относится к Python 3.x. В Python 2.x вы получите TypeError для вызова метода в самом классе.)

Например:

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)

В этом коде метод "rollCall" предполагает, что первый аргумент не является экземпляром (как это было бы, если бы он вызывался экземпляром, а не классом). Пока "rollCall" вызывается из класса, а не экземпляра, код будет работать нормально. Если мы попытаемся вызвать "rollCall" из экземпляра, например:

rex.rollCall(-1)

однако это привело бы к возникновению исключения, потому что оно отправило бы два аргумента: себя и -1, а "rollCall" определен для приема только одного аргумента.

Кстати, rex.rollCall() отправил бы правильное количество аргументов, но также вызвал бы возникновение исключения, потому что теперь n будет представлять экземпляр Dog (т. Е. rex), когда функция ожидает, что n будет числовым.

Вот тут-то и пригодится оформление: если мы начнем метод "rollCall" с

@staticmethod

затем, явно указав, что метод статический, мы можем даже вызвать его из экземпляра. Теперь,

rex.rollCall(-1)

будет работать. Таким образом, вставка @staticmethod перед определением метода останавливает отправку экземпляром самого себя в качестве аргумента.

Вы можете убедиться в этом, попробовав следующий код с закомментированной строкой @staticmethod или без нее.

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)
Ответ 3

Да, ознакомьтесь с декоратором staticmethod:

>>> class C:
... @staticmethod
... def hello():
... print "Hello World"
...
>>> C.hello()
Hello World
Ответ 4

На самом деле вам не нужно использовать @staticmethod декоратор. Просто объявите метод (который не ожидает параметра self ) и вызовите его из класса. Декоратор доступен только в том случае, если вы хотите иметь возможность вызывать его и из экземпляра (что было не тем, что вы хотели сделать)

Хотя в основном вы просто используете функции...

python