В чем преимущество использования статических методов в Python?


я столкнулся с несвязанной ошибкой метода в 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 выше, чтобы заставить код работать. Я новичок python. Может кто-нибудь объяснить, почему нужно определить статические методы? Или, почему не все методы определены как статические методы?

9 59

9 ответов:

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

поэтому они не полезны для повседневных методов.

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

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

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

посмотреть в этой статье для подробного объяснения.

TL; DR

1.It исключает использование

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

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

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

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

когда вы называете 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)

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

предположим, что у нас есть 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

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

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

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

статические методы почти не имеют оснований быть в 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

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

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

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

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

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

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