В чем преимущество использования статических методов в Python? - PullRequest
71 голосов
/ 13 марта 2010

Я столкнулся с ошибкой несвязанного метода в python с кодом

class Sample(object):
'''This class defines various methods related to the sample'''

    def drawSample(samplesize,List):
        sample=random.sample(List,samplesize)
        return sample

Choices=range(100)
print Sample.drawSample(5,Choices)

Прочитав много полезных постов здесь, я подумал, как можно добавить @staticmethod выше, чтобы код работал. Я новичок на питоне. Может кто-нибудь объяснить, почему можно определить статические методы? Или почему не все методы определены как статические методы?

Ответы [ 9 ]

151 голосов
/ 23 марта 2014

См. эту статью для подробного объяснения.

TL; DR

1.Это исключает использование аргумента self.

2. Это уменьшает использование памяти, потому что Python не должен создавать экземпляр bound-метода для каждого объекта:

>>>RandomClass().regular_method is RandomClass().regular_method
False
>>>RandomClass().static_method is RandomClass().static_method
True
>>>RandomClass.static_method is RandomClass().static_method
True

3. Это улучшает читабельность кода, показывая, что метод не зависит от состояния самого объекта.

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

97 голосов
/ 13 марта 2010

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

Так что они бесполезны для повседневных методов.

Однако они могут быть полезны для группировки некоторой функции полезности вместе с классом - например, простое преобразование из одного типа в другой - для этого не требуется доступ к какой-либо информации, кроме предоставленных параметров (и, возможно, некоторых атрибутов, глобальных для модуля).

Их можно размещать вне класса, но группировка их внутри класса может иметь смысл только там, где они применимы.

Вы также можете ссылаться на метод через экземпляр или класс, а не по имени модуля, что может помочь читателю понять, к какому экземпляру относится метод.

17 голосов
/ 13 марта 2010

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

Я бы никогда не исправил приведенный выше код, сделав метод статическим методом.Я бы либо исключил класс и просто написал функцию:

def drawSample(samplesize,List):
    sample=random.sample(List,samplesize)
    return sample

Choices=range(100)
print drawSample(5,Choices)

Если у вас много связанных функций, вы можете сгруппировать их в модуль - т.е. поместить их все в один файл с именем sample.py например;затем

import sample

Choices=range(100)
print sample.drawSample(5,Choices)

Или я бы добавил в класс метод init и создал бы экземпляр с полезными методами:

class Sample(object):
'''This class defines various methods related to the sample'''

    def __init__(self, thelist):
        self.list = thelist

    def draw_sample(self, samplesize):
        sample=random.sample(self.list,samplesize)
        return sample

choices=Sample(range(100))
print choices.draw_sample(5)

(я также изменилусловные обозначения в приведенном выше примере соответствуют стилю, рекомендованному PEP 8.)

Одним из преимуществ Python является то, что он не заставляет вас использовать классы для всего.Вы можете использовать их, только когда есть данные или состояние, которые должны быть связаны с методами, для чего предназначены классы.В противном случае вы можете использовать функции, для которых и предназначены функции.

13 голосов
/ 13 марта 2010

Почему нужно определить статические методы ?

Предположим, у нас есть class с именем Math, а затем

никто не захочет создать объект class Math
и затем вызовите методы как ceil и floor и fabs на нем.

Итак, мы делаем их static.

Например, делать

>> Math.floor(3.14)

намного лучше, чем

>> mymath = Math()
>> mymath.floor(3.14)

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

Почему не все методы определены как статические методы ?

У них нет доступа к переменным экземпляра.

class Foo(object):
    def __init__(self):
        self.bar = 'bar'

    def too(self):
        print self.bar

    @staticmethod
    def foo():
        print self.bar

Foo().too() # works
Foo.foo() # doesn't work

Именно поэтому мы не делаем все методы статичными.

12 голосов
/ 13 марта 2010

Когда вы вызываете объект функции из экземпляра объекта, он становится «связанным методом» и получает сам объект экземпляра, передаваемый в качестве первого аргумента.

Когда вы вызываете объект classmethod (который оборачивает объект функции) в экземпляре объекта, класс объекта экземпляра передается в качестве первого аргумента.

Когда вы вызываете объект staticmethod (который оборачивает объект функции), неявный первый аргумент не используется.

class Foo(object):

    def bar(*args):
        print args

    @classmethod
    def baaz(*args):
        print args

    @staticmethod
    def quux(*args):
        print args

>>> foo = Foo()

>>> Foo.bar(1,2,3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unbound method bar() must be called with Foo instance as first argument (got int instance instead)
>>> Foo.baaz(1,2,3)
(<class 'Foo'>, 1, 2, 3)
>>> Foo.quux(1,2,3)
(1, 2, 3)

>>> foo.bar(1,2,3)
(<Foo object at 0x1004a4510>, 1, 2, 3)
>>> foo.baaz(1,2,3)
(<class 'Foo'>, 1, 2, 3)
>>> foo.quux(1,2,3)
(1, 2, 3)
4 голосов
/ 13 марта 2010

статические методы хороши тем, что вам не нужно объявлять экземпляр объекта, которому принадлежит метод.

Сайт python содержит отличную документацию по статическим методам:
http://docs.python.org/library/functions.html#staticmethod

1 голос
/ 22 июня 2015

Поскольку функции пространств имен хороши (как было указано ранее):

  1. Когда я хочу открыто рассказать о методах, которые не меняют состояние объекта, я использую статические методы. Это отговаривает людей в моей команде начинать изменять атрибуты объекта в этих методах.

  2. Когда я реорганизую действительно гнилой код, я начинаю с попытки создать как можно больше методов @staticmethod. Это позволяет мне затем извлекать эти методы в класс - хотя я согласен, я редко использую это, это действительно помогало несколько раз.

0 голосов
/ 10 февраля 2018

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

Единственное, что я бы сказал, оправдывает их существование, это удобство. Статические методы распространены в других популярных языках программирования, так почему бы не Python? Если вы хотите создать функцию с поведением, которое очень тесно связано с классом, для которого вы ее создаете, но оно на самом деле не обращается к внутренним данным экземпляра класса и не изменяет их таким способом, который оправдывает концептуализацию этого как типичного затем метод этого класса набросит @staticmethod над ним, и любой, кто читает ваш код, сразу же узнает много нового о природе метода и его отношении к классу.

Одна вещь, которую я иногда люблю делать, это размещать функциональность, которую мой класс использует внутри себя, в частные @staticmethod s. Таким образом, я не загромождаю API, предоставляемый моим модулем, методами, которые никто, использующий мой модуль, никогда не должен видеть, не говоря уже об использовании.

0 голосов
/ 13 марта 2010

Статические методы почти не имеют причин быть в Python. Вы используете либо методы экземпляра, либо методы класса.

def method(self, args):
    self.member = something

@classmethod
def method(cls, args):
    cls.member = something

@staticmethod
def method(args):
    MyClass.member = something
    # The above isn't really working
    # if you have a subclass
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...