Я столкнулся с ошибкой несвязанного метода в python с кодом
import random
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
oop
static-methods
Любопытно
источник
источник
Ответы:
Статические методы имеют ограниченное использование, потому что у них нет доступа к атрибутам экземпляра класса (как у обычного метода), и у них нет доступа к атрибутам самого класса (как у метода класса ).
Поэтому они бесполезны для повседневных методов.
Однако они могут быть полезны для группировки некоторой служебной функции вместе с классом - например, для простого преобразования из одного типа в другой - которому не требуется доступ к какой-либо информации, кроме предоставленных параметров (и, возможно, некоторых атрибутов, глобальных для модуля. )
Они могут быть вынесены за пределы класса, но их группировка внутри класса может иметь смысл там, где они применимы только там.
Вы также можете ссылаться на метод через экземпляр или класс, а не через имя модуля, что может помочь читателю понять, к какому экземпляру относится метод.
источник
Locale
класса, экземпляры которого будут локали (да).getAvailableLocales()
Метод был бы хорошим пример метода статического такого класса: это явно принадлежит к классу Locale, а также явно не принадлежит к какому - либо конкретному случаю.class_name.attribute
, просто неcls.attribute
илиself.attribute
. Это верно для «общедоступных» атрибутов. По соглашению вам не следует обращаться к атрибутам, скрытым с подчеркиванием, или именам, искаженным двумя символами подчеркивания таким образом. Это также означает, что ваш код будет более хрупким, когда атрибуты смещаются в иерархии наследования.См. Эту статью для подробного объяснения.
TL; DR
1. Это исключает использование
self
аргументов.2. Это уменьшает использование памяти, потому что Python не должен создавать экземпляр метода привязки для каждого инициированного объекта:
>>>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. Это позволяет переопределить метод в том смысле, что если бы метод был определен на уровне модуля (т.е. вне класса), подкласс не смог бы переопределить этот метод.
источник
Это не совсем соответствует вашему фактическому вопросу, но, поскольку вы сказали, что являетесь новичком в 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 является то, что он не заставляет вас использовать классы для всего. Вы можете использовать их только тогда, когда есть данные или состояние, которые должны быть связаны с методами, для чего предназначены классы. В противном случае вы можете использовать функции, для которых они предназначены.
источник
Зачем нужно определять статические методы ?
Предположим, у нас есть
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
Вот почему мы не делаем все методы статическими.
источник
Math
. Вот почему я использовал заглавные буквыM
.Math
в первую очередь, нет причин для того, чтобы вы создавали класс, модуль был бы лучше. Попробуйте найти пример класса, который имеет смысл как класс, а не тот, из которого «никто не захочет создавать объект» .Когда вы вызываете объект функции из экземпляра объекта, он становится «связанным методом» и получает сам объект экземпляра, который передается в качестве первого аргумента.
Когда вы звоните
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)
источник
статические методы хороши тем, что вам не нужно объявлять экземпляр объекта, которому принадлежит метод.
На сайте python есть отличная документация по статическим методам:
http://docs.python.org/library/functions.html#staticmethod
источник
Альтернативы
staticmethod
являются:classmethod
,instancemethod
, иfunction
. Если вы не знаете, что это, прокрутите вниз до последнего раздела. Если astaticmethod
лучше любой из этих альтернатив, зависит от того, для какой цели он написан.преимущества статического метода Python
staticmethod
лучше, чемclassmethod
илиinstancemethod
. Таким образом становится ясно (из@staticmethod
декоратора), что состояние класса и экземпляра не читается и не изменяется. Однако использование afunction
делает это различие еще более четким (см. Недостатки).staticmethod
такая же, как уclassmethod
orinstancemethod
, а именно<instance>.<method>(<arguments>)
. Следовательно, его можно легко заменить одним из трех, если это понадобится позже или в производном классе. Вы не можете этого сделать с помощью простогоfunction
.staticmethod
можно использовать вместо a,function
чтобы показать, что он субъективно принадлежит классу, и предотвратить конфликты пространств имен.недостатки статического метода Python
staticmethod
такая же, как уclassmethod
илиinstancemethod
. Это маскирует тот факт, чтоstaticmethod
фактически не читает и не изменяет информацию об объекте. Это затрудняет чтение кода. Почему бы просто не использоватьfunction
?staticmethod
сложно повторно использовать, если вам когда-либо понадобится вызвать его извне класса / экземпляра, в котором он был определен. Если есть потенциал для повторного использования,function
лучшим выбором будет a .staticmethod
редко, поэтому людям, читающим код, который включает его, может потребоваться немного больше времени, чтобы прочитать его.альтернативы статическому методу в Python
Чтобы обратиться к обсуждению преимуществ
staticmethod
, нам нужно знать, какие есть альтернативы и чем они отличаются друг от друга.staticmethod
Принадлежит к классу , но не может получить доступ или изменить любую информацию экземпляра или класса.Этому есть три альтернативы:
classmethod
объекта есть доступ к классу вызывающего.instancemethod
объекта есть доступ к экземпляру вызывающего и его классу.function
имеет ничего общего с классами. По возможностям он наиболее близок кstaticmethod
.Вот как это выглядит в коде:
# function # has nothing to do with a class def make_cat_noise(asker_name): print('Hi %s, mieets mieets!' % asker_name) # Yey, we can make cat noises before we've even defined what a cat is! make_cat_noise('JOey') # just a function class Cat: number_of_legs = 4 # special instance method __init__ def __init__(self, name): self.name = name # instancemethod # the instance (e.g. Cat('Kitty')) is passed as the first method argument def tell_me_about_this_animal(self, asker_name): print('Hi %s, This cat has %d legs and is called %s' % (asker_name, self.number_of_legs, self.name)) # classmethod # the class (e.g. Cat) is passed as the first method argument # by convention we call that argument cls @classmethod def tell_me_about_cats(cls, asker_name): print("Hi %s, cats have %d legs." % (asker_name, cls.number_of_legs)) # cls.name # AttributeError because only the instance has .name # self.name # NameError because self isn't defined in this namespace # staticmethod # no information about the class or the instance is passed to the method @staticmethod def make_noise(asker_name): print('Hi %s, meooow!' % asker_name) # class and instance are not accessible from here # one more time for fun! make_cat_noise('JOey') # just a function # We just need the class to call a classmethod or staticmethod: Cat.make_noise('JOey') # staticmethod Cat.tell_me_about_cats('JOey') # classmethod # Cat.tell_me_about_this_animal('JOey') # instancemethod -> TypeError # With an instance we can use instancemethod, classmethod or staticmethod mycat = Cat('Kitty') # mycat is an instance of the class Cat mycat.make_noise('JOey') # staticmethod mycat.tell_me_about_cats('JOey') # classmethod mycat.tell_me_about_this_animal('JOey') # instancemethod
источник
Потому что функции пространства имен хороши (как было указано ранее):
Когда я хочу четко указать методы, которые не изменяют состояние объекта, я использую статические методы. Это отговаривает людей в моей команде начинать изменять атрибуты объекта в этих методах.
Когда я реорганизую действительно прогнивший код, я начинаю с попытки создать как можно больше методов
@staticmethod
. Это позволяет мне затем извлечь эти методы в класс - хотя я согласен, я редко использую это, но несколько раз помогал.источник
По моей оценке, нет единого преимущества в производительности от использования
@staticmethod
s по сравнению с простым определением функции вне и отдельно от класса, которым она в противном случае была бы@staticmethod
.Единственное, что оправдывает их существование, - это удобство. Статические методы распространены в других популярных языках программирования, так почему бы не использовать Python? Если вы хотите создать функцию с поведением, которое очень тесно связано с классом, для которого вы ее создаете, но на самом деле она не обращается / не изменяет внутренние данные экземпляра класса таким образом, который оправдывает концептуализацию его как типичного метод этого класса затем ударил
@staticmethod
над ним, и любой, кто читает ваш код, сразу узнает много о природе метода и его связи с классом.Иногда мне нравится помещать функциональные возможности, которые мой класс часто использует внутри себя, в private
@staticmethod
. Таким образом, я не загромождаю API, предоставляемый моим модулем, методами, которые никому, использующим мой модуль, никогда не понадобится, не говоря уже об использовании.источник
Статические методы практически не имеют смысла в 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
источник
staticmethod
или любое объяснение того , что такоеclassmethod
или почему и как это «лучше» , чем статические.staticmethod
подтверждающего ваше утверждение о несостоятельности или утверждение Георга, котороеclassmethod
следует использовать вместо этого).