Napotkałem niezwiązany błąd metody w Pythonie z kodem
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)
Po przeczytaniu wielu pomocnych postów pomyślałem, jak mogę dodać @staticmethod
powyżej, aby kod działał. Jestem nowicjuszem w Pythonie. Czy ktoś mógłby wyjaśnić, dlaczego chciałoby się zdefiniować metody statyczne? Albo dlaczego nie wszystkie metody są zdefiniowane jako metody statyczne?
python
oop
static-methods
Curious2learn
źródło
źródło
Odpowiedzi:
Metody statyczne mają ograniczone zastosowanie, ponieważ nie mają dostępu do atrybutów instancji klasy (jak ma to zwykła metoda) i nie mają dostępu do atrybutów samej klasy (tak jak metoda klasowa ).
Nie są więc przydatne w codziennych metodach.
Mogą być jednak przydatne do zgrupowania jakiejś funkcji narzędzia razem z klasą - np. Prosta konwersja z jednego typu na inny - która nie potrzebuje dostępu do żadnych informacji poza podanymi parametrami (i być może niektórych atrybutów globalnych dla modułu. )
Można je umieścić poza klasą, ale zgrupowanie ich wewnątrz klasy może mieć sens tam, gdzie mają zastosowanie tylko tam.
Możesz również odwoływać się do metody za pośrednictwem instancji lub klasy, a nie nazwy modułu, co może pomóc czytelnikowi zrozumieć, z jakim wystąpieniem metoda jest powiązana.
źródło
Locale
klasie, której instancje będą lokalnymi (duh).getAvailableLocales()
Metodą byłoby dobrym przykładem metody statycznej takiej klasy: to wyraźnie należą do klasy Locale, a także wyraźnie nie należą do żadnej konkretnej instancji.class_name.attribute
, po prostu niecls.attribute
lubself.attribute
. Dotyczy to atrybutów „publicznych”. Zgodnie z konwencją, w ten sposób nie należy uzyskiwać dostępu do atrybutów ukrytych za pomocą podkreślenia lub nazw zniekształconych dwoma podkreśleniami. Oznacza to również, że twój kod będzie bardziej kruchy, gdy atrybuty przesuną się o miejsca w hierarchii dziedziczenia.Zobacz ten artykuł, aby uzyskać szczegółowe wyjaśnienie.
TL; DR
1. eliminuje użycie
self
argumentu.Zmniejsza to zużycie pamięci, ponieważ Python nie musi tworzyć instancji metody powiązanej dla każdego instancjonowanego obiektu:
>>>RandomClass().regular_method is RandomClass().regular_method False >>>RandomClass().static_method is RandomClass().static_method True >>>RandomClass.static_method is RandomClass().static_method True
Poprawia czytelność kodu, co oznacza, że metoda nie zależy od stanu samego obiektu.
4. Pozwala na nadpisywanie metody w tym sensie, że gdyby metoda została zdefiniowana na poziomie modułu (tj. Poza klasą), podklasa nie byłaby w stanie przesłonić tej metody.
źródło
To nie jest do końca sedno twojego rzeczywistego pytania, ale skoro powiedziałeś, że jesteś nowicjuszem w Pythonie, być może będzie to pomocne, a nikt inny nie wyszedł i nie powiedział tego wyraźnie.
Nigdy nie naprawiłbym powyższego kodu, czyniąc metodę metodą statyczną. Albo porzuciłbym klasę i po prostu napisałbym funkcję:
def drawSample(samplesize,List): sample=random.sample(List,samplesize) return sample Choices=range(100) print drawSample(5,Choices)
Jeśli masz wiele powiązanych funkcji, możesz je zgrupować w module - tj. Umieścić je wszystkie w tym samym pliku, nazwanym
sample.py
na przykład; następnieimport sample Choices=range(100) print sample.drawSample(5,Choices)
Albo dodałbym
__init__
metodę do klasy i utworzyłbym instancję, która zawierałaby przydatne metody: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)
(Zmieniłem również konwencje przypadku w powyższym przykładzie, aby pasowały do stylu zalecanego przez PEP 8.)
Jedną z zalet Pythona jest to, że nie wymusza używania klas do wszystkiego. Możesz ich używać tylko wtedy, gdy istnieją dane lub stan, które powinny być skojarzone z metodami, do czego służą klasy. W przeciwnym razie możesz używać funkcji, do czego służą funkcje.
źródło
Dlaczego chciałoby się definiować metody statyczne ?
Załóżmy, że mamy wtedy
class
wezwanieMath
nikt nie będzie chciał tworzyć obiektu,
class Math
a następnie wywoływać metody takie jak
ceil
ifloor
ifabs
na nim.Więc je robimy
static
.Na przykład robienie
>> Math.floor(3.14)
jest znacznie lepszy niż
>> mymath = Math() >> mymath.floor(3.14)
Więc są w jakiś sposób przydatne. Nie musisz tworzyć instancji klasy, aby ich używać.
Dlaczego nie wszystkie metody są zdefiniowane jako metody statyczne ?
Nie mają dostępu do zmiennych instancji.
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
Dlatego nie wszystkie metody są statyczne.
źródło
Math
. Dlatego skapitalizowałemM
.Math
klasę w pierwszej kolejności, moduł byłby lepiej dopasowany. Spróbuj znaleźć przykład klasy, która miałaby sens jako klasa, a nie takiej, z której „nikt nie będzie chciał stworzyć obiektu” .Kiedy wywołujesz obiekt funkcji z instancji obiektu, staje się on „metodą powiązaną” i pobiera sam obiekt instancji jako pierwszy argument.
Kiedy wywołujesz
classmethod
obiekt (który opakowuje obiekt funkcji) w instancji obiektu, klasa obiektu instancji jest przekazywana jako pierwszy argument.Kiedy wywołujesz
staticmethod
obiekt (który otacza obiekt funkcji), nie jest używany żaden niejawny pierwszy argument.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)
źródło
metody statyczne są świetne, ponieważ nie musisz deklarować wystąpienia obiektu, do którego należy metoda.
Witryna pythona zawiera świetną dokumentację dotyczącą metod statycznych:
http://docs.python.org/library/functions.html#staticmethod
źródło
Alternatywy do A
staticmethod
to:classmethod
,instancemethod
, ifunction
. Jeśli nie wiesz, co to jest, przewiń w dół do ostatniej sekcji. Jeśli astaticmethod
jest lepsze niż którakolwiek z tych alternatyw, zależy to od tego, w jakim celu jest napisane.zalety statycznej metody Pythona
staticmethod
jest lepsze niżclassmethod
lubinstancemethod
. W ten sposób jest jasne (od@staticmethod
dekoratora), że stan klasy i instancji nie jest odczytywany ani modyfikowany. Jednak użycie znakufunction
sprawia, że to rozróżnienie jest jeszcze jaśniejsze (patrz wady).staticmethod
jest taki sam jak aclassmethod
lubinstancemethod
, a mianowicie<instance>.<method>(<arguments>)
. Dlatego można go łatwo zastąpić jednym z trzech, jeśli będzie to potrzebne później lub w klasie pochodnej. Nie możesz tego zrobić za pomocą prostegofunction
.staticmethod
Może być stosowany zamiastfunction
wyjaśnić, że to subiektywnie należy do klasy i aby uniknąć konfliktów nazw.wady statycznej metody Pythona
staticmethod
jest taki sam, jak podpis aclassmethod
lubinstancemethod
. To maskuje fakt, że wstaticmethod
rzeczywistości nie czyta ani nie modyfikuje żadnych informacji o obiekcie. To sprawia, że kod jest trudniejszy do odczytania. Dlaczego po prostu nie użyćfunction
?staticmethod
jest trudne do ponownego użycia, jeśli kiedykolwiek będziesz musiał wywołać go spoza klasy / instancji, w której został zdefiniowany. Jeśli istnieje jakikolwiek potencjał do ponownego wykorzystania,function
lepszym wyborem jest a.staticmethod
Jest rzadko używany, więc ludzie czytając kod, który zawiera jeden może trwać nieco dłużej, aby ją przeczytać.alternatywy dla metody statycznej w Pythonie
Aby omówić zalety programu
staticmethod
, musimy wiedzieć, jakie są alternatywy i czym się od siebie różnią.staticmethod
Należy do klasy, ale nie ma dostępu ani modyfikować żadnych instancji lub klasy informacje.Istnieją trzy alternatywy:
classmethod
Ma dostęp do klasy rozmówcy.instancemethod
Ma dostęp do instancji rozmówcy i jego klasę.function
ma to nic wspólnego z zajęciami. Jest najbliżej możliwości dostaticmethod
.Oto jak to wygląda w kodzie:
# 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
źródło
Ponieważ funkcje z przestrzenią nazw są fajne (jak wcześniej wskazano):
Kiedy chcę jasno określić metody, które nie zmieniają stanu obiektu, używam metod statycznych. To zniechęca ludzi w moim zespole do zmiany atrybutów obiektu w tych metodach.
Kiedy naprawiam naprawdę zgniły kod, zaczynam od stworzenia jak największej liczby metod
@staticmethod
. To pozwala mi następnie wyodrębnić te metody do klasy - chociaż zgadzam się, rzadko jest to coś, czego używam, przydało mi się kilka razy.źródło
W mojej ocenie, nie ma jednego wydajność zaletą korzystania
@staticmethod
s porównaniu do zaledwie definiowania poza funkcją i oddzielone od klasy byłoby inaczej@staticmethod
od.Jedyne, co powiedziałbym, że uzasadnia ich istnienie, to wygoda. Metody statyczne są powszechne w innych popularnych językach programowania, więc dlaczego nie python? Jeśli chcesz utworzyć funkcję z zachowaniem, które jest bardzo ściśle powiązane z klasą, dla której ją tworzysz, ale w rzeczywistości nie uzyskuje ona dostępu / modyfikuje wewnętrznych danych instancji klasy w sposób, który uzasadnia konceptualizację jej jako typowej metoda tej klasy, a następnie uderz
@staticmethod
ją powyżej, a każdy, kto czyta Twój kod, natychmiast nauczy się dużo o naturze metody i jej związku z klasą.Jedną z rzeczy, które czasami lubię robić, jest umieszczanie funkcji, z których moja klasa korzysta wewnętrznie, w prywatnych
@staticmethod
usługach. W ten sposób nie zaśmiecam interfejsu API udostępnianego przez mój moduł metodami, których nikt używający mojego modułu nigdy nie musiałby widzieć, nie mówiąc już o użyciu.źródło
Metody statyczne nie mają prawie żadnego powodu, by być w Pythonie. Używasz metod instancji lub metod klas.
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
źródło
staticmethod
ani żadnego wyjaśnienia, czymclassmethod
jest a, dlaczego i jak jest „lepsze” niż statyczne.staticmethod
które potwierdziłoby twoje twierdzenie, że jest to okrucieństwo lub twierdzenie Georga, któreclassmethod
powinno być użyte zamiast tego).