Есть ли преимущества использования метода @static?
Мне было интересно, используете ли вы @staticmethod decorator в своем коде.
Лично я не использую его, так как требуется больше писем для записи @staticmethod, затем self.
Единственное преимущество (которое приходит мне) от использования этого может быть лучшей ясностью кода, но поскольку я обычно пишу описание метода для sphinx, я всегда указываю, использует ли метод объект или нет.
Или, может быть, я должен начать использовать декоратор @staticmethod?
Ответы
Ответ 1
Использовать ли @staticmethod
или нет, зависит от того, чего вы хотите достичь. Игнорирование декоратора, потому что есть больше типа, это довольно глупая причина (без обид!) И указывает, что вы не поняли концепцию статического метода в Python!
Статические методы не зависят от класса и любого экземпляра класса. Они используют только область класса как пространство имен. Если вы опустите декоратор @staticmethod
, вы создаете метод экземпляра, который нельзя использовать без создания экземпляра.
Вот очень простой класс Foo
:
>>> class Foo(object):
... @staticmethod
... def foo():
... print 'foo'
...
... def bar(self):
... print 'bar'
Теперь Foo.foo()
- это статический метод, который можно вызвать напрямую:
>>> Foo.foo()
foo
Foo.bar()
, с другой стороны, это метод экземпляра, который может быть вызван только из экземпляров (объектов) Foo
:
>>> Foo.bar()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unbound method foo() must be called with Foo instance as first argument (got nothing instead)
>>> foo = Foo()
>>> foo.bar()
bar
Чтобы ответить на ваш вопрос: если вы хотите определить статический метод, используйте @staticmethod
. В противном случае, не делайте.
Если у вас есть метод, который не использует self
, и поэтому может быть записан как статический метод, спросите себя: хотите ли вы когда-нибудь получить доступ к этой функции извне без экземпляра? В большинстве случаев ответ будет: Нет.
Ответ 2
@staticmethod
Декоратор позволяет вам печатать и улучшать читаемость.
class Example:
@staticmethod
def some_method():
return
совпадает с:
class Example:
def some_method():
return
some_method = staticmethod(some_method)
Я думаю, вы можете быть смущены тем, что статический метод находится в Python, поскольку терминология отличается от других языков. Обычный метод "привязан" к экземпляру (self
), метод класса "привязан" к классу (cls
), а статический метод вообще не "привязан" (и не может получить доступ к экземпляру или классу атрибуты.
См:
Ответ 3
Предположим, что мы хотим определить метод abs
в классе Math
, тогда у нас есть два варианта:
class Math():
def abs(n):
if n>0:
return n
else:
return -n
class Math2():
@staticmethod
def abs(n):
if n>0:
return n
else:
return -n
В Python2:
>>> Math.abs(-2)
TypeError: unbound method abs() must be called with Math instance as
first argument (got int instance instead)
>>>Math().abs(-2)
TypeError: abs() takes exactly 1 argument (2 given)
>>> Math2.abs(-2)
2
>>> Math2().abs(-2)
2
python2 автоматически принимает Math().abs(-2)
как Math().abs(self,-2)
, поэтому вам нужно использовать @staticmethod
.
В Python3
>>>Math.abs(-3)
3
>>>Math().abs(-3)
TypeError: abs() takes 1 positional argument but 2 were given
>>>Math2.abs(-3)
3
>>>Math2().abs(-3)
3
В python3 вы можете использовать classname.method()
без статического метода, но он будет поднимать TypeError, когда кто-то пытается использовать instance.method()
.