Статические методы в 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 ) и вызовите его из класса. Декоратор доступен только в том случае, если вы хотите иметь возможность вызывать его и из экземпляра (что было не тем, что вы хотели сделать)
Хотя в основном вы просто используете функции...