Różnica między staticmethod i classmethod
Jaka jest różnica między funkcją zdobioną @staticmethod
i jeden ozdobiony @classmethod
?
30 answers
Może trochę przykładowego kodu pomoże: zauważ różnicę w sygnaturze wywołaniafoo
, class_foo
i static_foo
:
class A(object):
def foo(self, x):
print "executing foo(%s, %s)" % (self, x)
@classmethod
def class_foo(cls, x):
print "executing class_foo(%s, %s)" % (cls, x)
@staticmethod
def static_foo(x):
print "executing static_foo(%s)" % x
a = A()
Poniżej znajduje się zwykły sposób, w jaki instancja obiektu wywołuje metodę. Instancja obiektu a
jest domyślnie przekazywana jako pierwszy argument.
a.foo(1)
# executing foo(<__main__.A object at 0xb7dbef0c>,1)
W przypadku classmethods , klasa instancji obiektu jest domyślnie przekazywana jako pierwszy argument zamiast self
.
a.class_foo(1)
# executing class_foo(<class '__main__.A'>,1)
Możesz również wywołać class_foo
używając klasy. W rzeczywistości, jeśli definiujesz coś jako
classmethod, prawdopodobnie dlatego, że zamierzasz wywołać go z klasy, a nie z instancji klasy. A.foo(1)
podniosłoby TypeError, aleA.class_foo(1)
działa dobrze: {]}
A.class_foo(1)
# executing class_foo(<class '__main__.A'>,1)
Jednym z zastosowań, jakie ludzie znaleźli dla metod klasowych, jest tworzenie dziedzicznych konstruktorów alternatywnych .
W staticmethods , ani self
(instancja obiektu), ani cls
(klasa) nie są domyślnie przekazywane jako pierwszy argument. Zachowują się podobnie jak zwykłe funkcje, z tym wyjątkiem, że można je wywołać z instancji lub klasy:
a.static_foo(1)
# executing static_foo(1)
A.static_foo('hi')
# executing static_foo(hi)
Staticmethods są używane do grupowania funkcji, które mają pewne logiczne połączenie z klasą do klasy.
foo
jest tylko funkcją, ale kiedy wywołujesz a.foo
Nie otrzymujesz tylko funkcji,
otrzymujemy "częściowo zastosowaną" wersję funkcji z instancją obiektu a
przypisaną jako pierwszy argument do funkcji. foo
oczekuje 2 argumentów, podczas gdy a.foo
oczekuje tylko 1 kłótnia.
a
jest związana z foo
. To jest to, co oznacza termin "związany" poniżej:
print(a.foo)
# <bound method A.foo of <__main__.A object at 0xb7d52f0c>>
Z a.class_foo
, a
nie jest związana z class_foo
, A Klasa A
jest związana z class_foo
.
print(a.class_foo)
# <bound method type.class_foo of <class '__main__.A'>>
Tutaj, ze staticmethod, mimo że jest to metoda, a.static_foo
po prostu zwraca
dobra funkcja ' ole bez żadnych argumentów. static_foo
oczekuje 1 argumentu i
a.static_foo
oczekuje również 1 argumentu.
print(a.static_foo)
# <function static_foo at 0xb7d479cc>
I oczywiście to samo dzieje się, gdy dzwonisz static_foo
z Klasa A
zamiast.
print(A.static_foo)
# <function static_foo at 0xb7d479cc>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-03-01 18:34:27
A staticmethod jest metodą, która nie wie nic o klasie lub instancji, do której została wywołana. Po prostu dostaje argumenty, które zostały przekazane, bez ukrytego pierwszego argumentu. Jest to w zasadzie bezużyteczne w Pythonie - możesz po prostu użyć funkcji modułu zamiast staticmethod.
A classmethod , z drugiej strony, jest metodą, która jako pierwszy argument przekazuje klasę, na którą została wywołana, lub klasę instancji, na którą została wywołana. Jest to przydatne, gdy chcesz, aby metoda być fabryką dla klasy: ponieważ otrzymuje ona rzeczywistą klasę, na której została wywołana jako pierwszy argument, zawsze możesz utworzyć instancję odpowiedniej klasy, nawet jeśli zaangażowane są podklasy. Zauważ na przykład, jak dict.fromkeys()
, classmethod, zwraca instancję podklasy, gdy jest wywoływana na podklasie:
>>> class DictSubclass(dict):
... def __repr__(self):
... return "DictSubclass"
...
>>> dict.fromkeys("abc")
{'a': None, 'c': None, 'b': None}
>>> DictSubclass.fromkeys("abc")
DictSubclass
>>>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-27 13:00:36
Zasadniczo @classmethod
tworzy metodę, której pierwszym argumentem jest klasa, z której jest wywoływana (a nie instancja klasy), @staticmethod
nie ma żadnych ukrytych argumentów.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-08 02:07:54
Oficjalne dokumenty Pythona:
Metoda klasowa otrzymuje klasę jako implicit pierwszy argument, podobnie jak instancja otrzymuje instancję. Aby zadeklarować metodę klasy, użyj tego idiom:
class C: @classmethod def f(cls, arg1, arg2, ...): ...
Forma
@classmethod
jest funkcją dekorator – zobacz opis definicje funkcji w funkcja definicje Po szczegóły.Może być wywoływane albo na zajęciach (np.
C.f()
) lub na instancji (np.C().f()
). Instancja jest ignorowane z wyjątkiem swojej klasy. Jeśli a metodę klasową nazywa się pochodną klasy, obiekt klasy pochodnej jest przekazany jako domniemany pierwszy argument.Metody klasowe różnią się od C++ lub statycznych metod Javy. Jeśli chcesz Zobacz też
staticmethod()
w tym sekcja.
Statyczna metoda nie otrzymuje Ukryty pierwszy argument. Aby zadeklarować metoda statyczna, użyj tego idiomu:
class C: @staticmethod def f(arg1, arg2, ...): ...
Forma
@staticmethod
jest funkcją dekorator – zobacz opis definicje funkcji w funkcja definicje Po szczegóły.Może być wywołana albo na klasie (np.
C.f()
) lub na instancji (np.C().f()
). Instancja jest ignorowane z wyjątkiem swojej klasy.Statyczne metody w Pythonie są podobne do znalezionych w Javie lub C++. Na bardziej zaawansowana koncepcja, zobacz
classmethod()
w tej sekcji.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-11 09:56:07
Tutaj {[2] } jest krótki artykuł na to pytanie
@staticmethod funkcja jest niczym innym jak funkcją zdefiniowaną wewnątrz klasy. Można go wywołać bez tworzenia instancji klasy. Jego definicja jest niezmienna poprzez dziedziczenie.
@ classmethod funkcja również może być wywołana bez tworzenia instancji klasy, ale jej definicja wynika z podklasy, Nie klasy nadrzędnej, poprzez dziedziczenie. To dlatego, że pierwszym argumentem dla funkcji @ classmethod musi być zawsze cls (Klasa).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55
Aby zdecydować, czy użyć @ staticmethod Czy @classmethod musisz zajrzeć do swojej metody. Jeśli twoja metoda uzyskuje dostęp do innych zmiennych / metod w twojej klasie, użyj @classmethod . Z drugiej strony, jeśli twoja metoda nie dotyka innych części klasy, użyj @staticmethod.
class Apple:
_counter = 0
@staticmethod
def about_apple():
print('Apple is good for you.')
# note you can still access other member of the class
# but you have to use the class instance
# which is not very nice, because you have repeat yourself
#
# For example:
# @staticmethod
# print('Number of apples have been juiced: %s' % Apple._counter)
#
# @classmethod
# print('Number of apples have been juiced: %s' % cls._counter)
#
# @classmethod is especially useful when you move your function to other class,
# you don't have to rename the class reference
@classmethod
def make_apple_juice(cls, number_of_apples):
print('Make juice:')
for i in range(number_of_apples):
cls._juice_this(i)
@classmethod
def _juice_this(cls, apple):
print('Juicing %d...' % apple)
cls._counter += 1
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-05 14:45:30
Jaka jest różnica między @staticmethod i @classmethod w Pythonie?
Być może widziałeś Kod Pythona taki jak ten pseudokod, który demonstruje sygnatury różnych typów metod i zapewnia docstring do wyjaśnienia każdego z nich:
class Foo(object):
def a_normal_instance_method(self, arg_1, kwarg_2=None):
'''
Return a value that is a function of the instance with its
attributes, and other arguments such as arg_1 and kwarg2
'''
@staticmethod
def a_static_method(arg_0):
'''
Return a value that is a function of arg_0. It does not know the
instance or class it is called from.
'''
@classmethod
def a_class_method(cls, arg1):
'''
Return a value that is a function of the class and other arguments.
respects subclassing, it is called with the class it is called from.
'''
Metoda Instancji Normalnej
Najpierw wyjaśnię a_normal_instance_method
. Jest to dokładnie tak zwana " metoda instancji ". Gdy używana jest metoda instancji, jest ona używana jako funkcja częściowa (w przeciwieństwie do całkowitej funkcja, zdefiniowana dla wszystkich wartości w kodzie źródłowym), to znaczy, gdy jest używana, pierwszy z argumentów jest predefiniowany jako instancja obiektu, ze wszystkimi jego podanymi atrybutami. Ma przypisaną instancję obiektu i musi być wywołana z instancji obiektu. Zazwyczaj uzyskuje dostęp do różnych atrybutów instancji.
', '
Jeśli użyjemy metody instancji, join
na tym łańcuchu, aby połączyć inny iterable,
jest to oczywiście funkcja instancji, oprócz tego, że jest funkcją listy iterowalnej, ['a', 'b', 'c']
:
>>> ', '.join(['a', 'b', 'c'])
'a, b, c'
Metody wiązania
Przykładowe metody mogą być powiązane za pomocą przerywanego wyszukiwania do użycia później.
Na przykład wiąże metodę str.join
z instancją ':'
:
>>> join_with_colons = ':'.join
I później możemy użyć tego jako funkcji, która ma już przypisany pierwszy argument. W ten sposób działa jak funkcja częściowa na instancja:
>>> join_with_colons('abcde')
'a:b:c:d:e'
>>> join_with_colons(['FF', 'FF', 'FF', 'FF', 'FF', 'FF'])
'FF:FF:FF:FF:FF:FF'
Metoda Statyczna
Metoda statyczna nie przyjmuje instancji jako argumentu.
Jest bardzo podobna do funkcji poziomu modułu.
Jednak funkcja poziomu modułu musi żyć w module i być specjalnie zaimportowana do innych miejsc, w których jest używana.
Jeśli jednak jest on dołączony do obiektu, będzie podążał za nim wygodnie poprzez importowanie i dziedziczenie.
Przykładem metody statycznej jest str.maketrans
, przeniesiony z modułu string
w Pythonie 3. To sprawia, że tabela tłumaczenia nadaje się do spożycia przez str.translate
. Jest to dość głupie, gdy jest używane z instancji łańcucha znaków, jak pokazano poniżej, ale importowanie funkcji z modułu string
jest raczej niezdarne i miło jest być w stanie wywołać ją z klasy, jak w str.maketrans
# demonstrate same function whether called from instance or not:
>>> ', '.maketrans('ABC', 'abc')
{65: 97, 66: 98, 67: 99}
>>> str.maketrans('ABC', 'abc')
{65: 97, 66: 98, 67: 99}
W Pythonie 2, musisz zaimportować tę funkcję z coraz mniej użytecznego modułu string:
>>> import string
>>> 'ABCDEFG'.translate(string.maketrans('ABC', 'abc'))
'abcDEFG'
Metoda Klasy
A metoda klasy jest podobna do metody instancji, ponieważ pobiera pierwszy argument ukryty, ale zamiast brać instancję, bierze klasę. Często są one używane jako alternatywne konstruktory dla lepszego wykorzystania semantycznego i będą wspierać dziedziczenie.
Najbardziej kanonicznym przykładem zbudowanej klasy jest dict.fromkeys
. Jest on używany jako alternatywny konstruktor dict, (dobrze nadaje się do tego, gdy wiesz, jakie są Twoje klucze i chcesz dla nich domyślną wartość.)
>>> dict.fromkeys(['a', 'b', 'c'])
{'c': None, 'b': None, 'a': None}
Kiedy podklasa dict, możemy użyć tego samego konstruktora, który tworzy instancję podklasy.
>>> class MyDict(dict): 'A dict subclass, use to demo classmethods'
>>> md = MyDict.fromkeys(['a', 'b', 'c'])
>>> md
{'a': None, 'c': None, 'b': None}
>>> type(md)
<class '__main__.MyDict'>
Zobacz kod źródłowy pandas dla innych podobnych przykładów alternatywnych konstruktorów, a także zobacz oficjalną dokumentację Pythona na classmethod
oraz staticmethod
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55
Zacząłem uczyć się języka programowania z C++, a następnie Java i Python, więc to pytanie bardzo mnie niepokoiło, dopóki nie zrozumiałem prostego użycia każdego z nich.
Metoda klasowa: Python w przeciwieństwie do Javy i C++ nie ma przeciążenia konstruktora. Aby to osiągnąć, możesz użyć classmethod
. Poniższy przykład wyjaśni to
Rozważmy, że mamy Person
klasę, która pobiera dwa argumenty first_name
i last_name
i tworzy instancję Person
.
class Person(object):
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
Teraz, jeśli wymagane jest utworzenie klasy używającej tylko jednej nazwy, tylko first_name
, nie możesz zrobić czegoś takiego w Pythonie.
Spowoduje to błąd podczas próby utworzenia obiektu (instancji).
class Person(object):
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
def __init__(self, first_name):
self.first_name = first_name
Można jednak osiągnąć to samo za pomocą @classmethod
, Jak wspomniano poniżej
class Person(object):
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
@classmethod
def get_person(cls, first_name):
return cls(first_name, "")
Metoda statyczna: jest to dość proste, nie jest związane z instancją lub klasą i można po prostu wywołać to użycie nazwy klasy.
Załóżmy więc, że w powyższym przykładzie potrzebujesz walidacji, która first_name
nie powinna przekraczać 20 znaków, możesz to po prostu zrobić.
@staticmethod
def validate_name(name):
return len(name) <= 20
I możesz po prostu zadzwonić używając class name
Person.validate_name("Gaurang Shah")
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-04-16 14:21:15
Myślę, że lepszym pytaniem jest "kiedy użyłbyś @classmethod
vs @staticmethod
?"
@classmethod
umożliwia łatwy dostęp do prywatnych członków powiązanych z definicją klasy. jest to świetny sposób na wykonywanie singletonów lub klas fabrycznych, które kontrolują liczbę wystąpień utworzonych obiektów.
@staticmethod
zapewnia marginalne zyski wydajności, ale nie widzę jeszcze produktywnego wykorzystania metody statycznej w klasie, której nie można osiągnąć jako samodzielnej funkcji poza klasy.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-08-13 21:32:31
Metody Statyczne:
- Proste funkcje bez własnego argumentu.
- pracuj nad atrybutami klasy, nie nad atrybutami instancji.
- może być wywołana zarówno przez klasę, jak i instancję.
- wbudowana funkcja staticmethod () jest używana do ich tworzenia.
Zalety metod statycznych:
- lokalizuje nazwę funkcji w classscope
- przesuwa kod funkcji bliżej miejsca, w którym jest używany
-
Wygodniej aby zaimportować funkcje na poziomie modułu, ponieważ każda metoda nie musi być specjalnie zaimportowana
@staticmethod def some_static_method(*args, **kwds): pass
Metody Klasy:
- funkcje, które mają pierwszy argument jako classname.
- może być wywołana zarówno przez klasę, jak i instancję.
-
Są one tworzone za pomocą wbudowanej funkcji classmethod.
@classmethod def some_class_method(cls, *args, **kwds): pass
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-14 03:10:25
@dekoratory zostały dodane w Pythonie 2.4 jeśli używasz Pythona
Na przykład, jeśli chcesz utworzyć metodę fabryczną (funkcję zwracającą instancję innej implementacji klasy w zależności od tego, jaki argument otrzyma), możesz zrobić coś w stylu:
class Cluster(object):
def _is_cluster_for(cls, name):
"""
see if this class is the cluster with this name
this is a classmethod
"""
return cls.__name__ == name
_is_cluster_for = classmethod(_is_cluster_for)
#static method
def getCluster(name):
"""
static factory method, should be in Cluster class
returns a cluster object for the given name
"""
for cls in Cluster.__subclasses__():
if cls._is_cluster_for(name):
return cls()
getCluster = staticmethod(getCluster)
Zauważ również, że jest to dobry przykład użycia metody classmethod i statycznej, Metoda statyczna wyraźnie należy do klasy, ponieważ wykorzystuje klaster klasy wewnętrznie. Classmethod potrzebuje jedynie informacji o klasie i żadnej instancji obiektu.
Kolejną zaletą uczynienia metody _is_cluster_for
klasą classmethod jest to, że podklasa może zdecydować się na zmianę jej implementacji, może dlatego, że jest dość ogólna i może obsługiwać więcej niż jeden typ klastra, więc samo sprawdzanie nazwy klasy nie wystarczy.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-20 15:34:34
Różni się tylko pierwszy argument :
- normalna metoda: bieżący obiekt Jeśli automatycznie przekazany jako (dodatkowy) pierwszy argument
- classmethod: Klasa bieżącego obiektu jest automatycznie przekazywana jako (dodatkowy) argument pięści
- staticmethod: żadne dodatkowe argumenty nie są przekazywane automatycznie. To, co przekazałeś do funkcji, jest tym, co dostajesz.
Bardziej szczegółowo...
Normal metoda
Gdy metoda obiektu jest wywoływana, automatycznie otrzymuje dodatkowy argument self
jako pierwszy argument. Czyli metoda
def f(self, x, y)
Musi być wywołane z 2 argumentami. self
jest automatycznie przekazywany i jest tosam obiekt .
Metoda klasy
Gdy metoda jest dekorowana
@classmethod
def f(cls, x, y)
Automatycznie podany argument nie jest self
, ale Klasa self
.
Metoda statyczna
Gdy metoda zdobiona
@staticmethod
def f(x, y)
Metoda nie jest podana w ogóle żaden argument automatyczny. Podano tylko parametry, z którymi jest wywoływany.
Zastosowania
-
classmethod
jest najczęściej używany dla konstruktorów alternatywnych. -
staticmethod
nie używa stanu obiektu. Może to być funkcja zewnętrzna do klasy. Umieszczanie wewnątrz klasy tylko w celu grupowania funkcji o podobnej funkcjonalności (na przykład, jak statyczna Klasa JavyMath
metody)
class Point
def __init__(self, x, y):
self.x = x
self.y = y
@classmethod
def frompolar(cls, radius, angle):
"""The `cls` argument is the `Point` class itself"""
return cls(radius * cos(angle), radius * sin(angle))
@staticmethod
def angle(x, y):
"""this could be outside the class, but we put it here
just because we think it is logically related to the class."""
return atan(y, x)
p1 = Point(3, 2)
p2 = Point.frompolar(3, pi/4)
angle = Point.angle(3, 2)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55
Pozwól, że najpierw przedstawię podobieństwo między metodą oznaczoną @classmethod a @staticmethod.
Podobieństwo: oba mogą być wywoływane na samej klasie , a nie tylko na instancjiklasy. Tak więc obie z nich w pewnym sensie są metodami Klasy .
Różnica: classmethod otrzyma klasę jako pierwszy argument, podczas gdy staticmethod nie.
Więc metoda statyczna nie jest w pewnym sensie związana z klasa sama w sobie i wisi tam tylko dlatego, że może mieć powiązaną funkcjonalność.
>>> class Klaus:
@classmethod
def classmthd(*args):
return args
@staticmethod
def staticmthd(*args):
return args
# 1. Call classmethod without any arg
>>> Klaus.classmthd()
(__main__.Klaus,) # the class gets passed as the first argument
# 2. Call classmethod with 1 arg
>>> Klaus.classmthd('chumma')
(__main__.Klaus, 'chumma')
# 3. Call staticmethod without any arg
>>> Klaus.staticmthd()
()
# 4. Call staticmethod with 1 arg
>>> Klaus.staticmthd('chumma')
('chumma',)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-11-08 03:36:22
@staticmethod
po prostu wyłącza domyślną funkcję jako deskryptor metody. classmethod zawija funkcję w kontenerze, który przekazuje odwołanie do klasy posiadającej jako pierwszy argument:
>>> class C(object):
... pass
...
>>> def f():
... pass
...
>>> staticmethod(f).__get__(None, C)
<function f at 0x5c1cf0>
>>> classmethod(f).__get__(None, C)
<bound method type.f of <class '__main__.C'>>
W rzeczywistości, classmethod
ma narzut runtime, ale umożliwia dostęp do klasy posiadającej. Alternatywnie zalecam użycie metaclass i umieszczenie metod klasy na tej metaclass:
>>> class CMeta(type):
... def foo(cls):
... print cls
...
>>> class C(object):
... __metaclass__ = CMeta
...
>>> C.foo()
<class '__main__.C'>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-25 21:24:13
Definitywny Przewodnik Jak używać statycznych, klasowych lub abstrakcyjnych metod w Pythonie jest dobrym linkiem do tego tematu i podsumowaniem go w następujący sposób.
@staticmethod
funkcja jest niczym innym jak funkcją zdefiniowaną wewnątrz klasy. Można go wywołać bez tworzenia instancji klasy. Jego definicja jest niezmienna poprzez dziedziczenie.
- Python nie musi tworzyć instancji bound-method dla obiektu. [[12]}ułatwia czytelność kodu, a nie zależy od stanu samego obiektu;
@classmethod
funkcja może być również wywołana bez tworzenia instancji klasy, ale jej definicja jest następująca po podklasie, a nie klasie nadrzędnej, poprzez dziedziczenie, może być nadpisana przez podklasę. To dlatego, że pierwszym argumentem dla @classmethod
funkcji musi być cls (class).
- metody fabryczne , które są używane do tworzenia instancji klasy przy użyciu na przykład pewnego rodzaju wstępnego przetwarzania.
- Static metody wywołujące statyczne metody: jeśli podzielisz statyczne metody na kilka statycznych metod, nie powinieneś kodować nazwy klasy, ale używać metod klasy
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-12 15:21:41
Kolejna uwaga dotycząca staticmethod vs classmethod pojawia się z dziedziczeniem. Powiedzmy, że masz następującą klasę:
class Foo(object):
@staticmethod
def bar():
return "In Foo"
A następnie chcesz zastąpić bar()
w klasie dziecięcej:
class Foo2(Foo):
@staticmethod
def bar():
return "In Foo2"
To działa, ale zauważ, że teraz implementacja bar()
w klasie potomnej (Foo2
) nie może już korzystać z niczego specyficznego dla tej klasy. Na przykład, powiedzmy Foo2
miał metodę o nazwie magic()
, którą chcesz użyć w Foo2
implementacji bar()
:
class Foo2(Foo):
@staticmethod
def bar():
return "In Foo2"
@staticmethod
def magic():
return "Something useful you'd like to use in bar, but now can't"
Obejściem byłoby wywołanie Foo2.magic()
W bar()
, ale potem powtarzasz się (jeśli nazwa Foo2
się zmieni, musisz pamiętać, aby zaktualizować tę metodę bar()
).
Dla mnie jest to niewielkie naruszenie Zasady open/closed , ponieważ decyzja podjęta w Foo
wpływa na Twoją zdolność do refaktoryzacji wspólnego kodu w klasie pochodnej (tj. jest mniej otwarta na rozszerzenie). Gdyby bar()
były {[17] }bylibyśmy w porządku:
class Foo(object):
@classmethod
def bar(cls):
return "In Foo"
class Foo2(Foo):
@classmethod
def bar(cls):
return "In Foo2 " + cls.magic()
@classmethod
def magic(cls):
return "MAGIC"
print Foo2().bar()
Daje: In Foo2 MAGIC
Także: notatka historyczna: Guido Van Rossum (twórca Pythona) kiedyś określił go jako "wypadek": https://mail.python.org/pipermail/python-ideas/2012-May/014969.html
Wszyscy wiemy, jak ograniczone są metody statyczne. (Są one w zasadzie przypadkiem - w czasach Pythona 2.2, kiedy wymyślałem nowe klasy i deskryptory, miałem na myśli implementację metod klas, ale na początku ich nie rozumiałem i przypadkowo zaimplementowałem statyczne najpierw metody. Wtedy było już za późno, aby je usunąć i podać tylko metody klasowe.
Także: https://mail.python.org/pipermail/python-ideas/2016-July/041189.html
Szczerze mówiąc, staticmethod był czymś w rodzaju błędu - próbowałem zrobić coś takiego jak Java class methods, ale po wydaniu okazało się, że to, co było naprawdę potrzebne, to classmethod. Ale było już za późno na pozbycie się staticmethod.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2021-02-10 21:13:00
Postaram się wyjaśnić podstawową różnicę na przykładzie.
class A(object):
x = 0
def say_hi(self):
pass
@staticmethod
def say_hi_static():
pass
@classmethod
def say_hi_class(cls):
pass
def run_self(self):
self.x += 1
print self.x # outputs 1
self.say_hi()
self.say_hi_static()
self.say_hi_class()
@staticmethod
def run_static():
print A.x # outputs 0
# A.say_hi() # wrong
A.say_hi_static()
A.say_hi_class()
@classmethod
def run_class(cls):
print cls.x # outputs 0
# cls.say_hi() # wrong
cls.say_hi_static()
cls.say_hi_class()
1 - możemy bezpośrednio wywoływać static i classmethods bez inicjalizacji
# A.run_self() # wrong
A.run_static()
A.run_class()
2-metoda statyczna nie może wywoływać metody self, ale może wywoływać inne metody statyczne i classmethod
3-metoda statyczna należy do klasy i w ogóle nie będzie używać obiektu.
4-klasowe metody nie są powiązane z obiektem, lecz z klasą.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-20 09:03:29
@ classmethod: może być użyty do utworzenia wspólnego globalnego dostępu do wszystkich instancji utworzonych w tej klasie..... jak aktualizacja rekordu przez wielu użytkowników.... Szczególnie zauważyłem, że używa się go również przy tworzeniu singletonów..:)
@ static metoda: nie ma nic wspólnego z klasą lub instancją, z którą jest skojarzona ...ale dla czytelności można użyć metody statycznej
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-20 17:07:01
Metoda klasowa otrzymuje klasę jako pierwszy argument, podobnie jak metoda instancji otrzymuje instancję. Jest to metoda, która jest związana z klasą, A nie obiektem class.It ma dostęp do stanu klasy, ponieważ pobiera parametr klasy, który wskazuje na klasę, A nie instancję obiektu. Może modyfikować stan klasy, który miałby zastosowanie we wszystkich instancjach klasy. Na przykład może modyfikować zmienną klasy, która będzie miała zastosowanie do wszystkich wystąpień.
Z drugiej strony, statyczna metoda nie otrzymuje pierwszego argumentu, w porównaniu do metod klasy lub instancji. I nie można uzyskać dostępu ani modyfikować stanu klasy. Należy tylko do klasy, ponieważ z punktu widzenia projektowania jest to właściwa droga. Ale pod względem funkcjonalności nie jest związany, w czasie wykonywania, do klasy.
Jako wytyczne, użyj metod statycznych jako narzędzi, użyj metod klasowych na przykład jako factory . A może dla określenia Singletona. I używać metod instancji modelowanie stanu i zachowania instancji.
Mam nadzieję, że wyraziłem się jasno !
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-11-20 11:48:00
Możesz rozważyć różnicę między:
class A:
def foo(): # no self parameter, no decorator
pass
I
class B:
@staticmethod
def foo(): # no self parameter
pass
To się zmieniło między python2 i python3:
Pyton2:
>>> A.foo()
TypeError
>>> A().foo()
TypeError
>>> B.foo()
>>> B().foo()
Pyton3:
>>> A.foo()
>>> A().foo()
TypeError
>>> B.foo()
>>> B().foo()
Więc używanie @staticmethod
dla metod wywoływanych TYLKO bezpośrednio z klasy stało się opcjonalne w python3. Jeśli chcesz wywołać je zarówno z klasy, jak I instancji, nadal musisz użyć dekoratora @staticmethod
.
Pozostałe przypadki zostały dobrze omówione przez unutbus answer.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-09-14 12:00:30
Mój wkład pokazuje różnicę między @classmethod
, @staticmethod
, i metody instancji, w tym sposób, w jaki instancja może pośrednio wywoływać @staticmethod
. Ale zamiast pośrednio wywoływać @staticmethod
z instancji, uczynienie jej prywatną może być bardziej " pythoniczne."Uzyskanie czegoś z prywatnej metody nie jest tutaj zademonstrowane, ale zasadniczo jest to ta sama koncepcja.
#!python3
from os import system
system('cls')
# % % % % % % % % % % % % % % % % % % % %
class DemoClass(object):
# instance methods need a class instance and
# can access the instance through 'self'
def instance_method_1(self):
return 'called from inside the instance_method_1()'
def instance_method_2(self):
# an instance outside the class indirectly calls the static_method
return self.static_method() + ' via instance_method_2()'
# class methods don't need a class instance, they can't access the
# instance (self) but they have access to the class itself via 'cls'
@classmethod
def class_method(cls):
return 'called from inside the class_method()'
# static methods don't have access to 'cls' or 'self', they work like
# regular functions but belong to the class' namespace
@staticmethod
def static_method():
return 'called from inside the static_method()'
# % % % % % % % % % % % % % % % % % % % %
# works even if the class hasn't been instantiated
print(DemoClass.class_method() + '\n')
''' called from inside the class_method() '''
# works even if the class hasn't been instantiated
print(DemoClass.static_method() + '\n')
''' called from inside the static_method() '''
# % % % % % % % % % % % % % % % % % % % %
# >>>>> all methods types can be called on a class instance <<<<<
# instantiate the class
democlassObj = DemoClass()
# call instance_method_1()
print(democlassObj.instance_method_1() + '\n')
''' called from inside the instance_method_1() '''
# # indirectly call static_method through instance_method_2(), there's really no use
# for this since a @staticmethod can be called whether the class has been
# instantiated or not
print(democlassObj.instance_method_2() + '\n')
''' called from inside the static_method() via instance_method_2() '''
# call class_method()
print(democlassObj.class_method() + '\n')
''' called from inside the class_method() '''
# call static_method()
print(democlassObj.static_method())
''' called from inside the static_method() '''
"""
# whether the class is instantiated or not, this doesn't work
print(DemoClass.instance_method_1() + '\n')
'''
TypeError: TypeError: unbound method instancemethod() must be called with
DemoClass instance as first argument (got nothing instead)
'''
"""
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-25 02:38:52
Analizuj @ staticmethod dosłownie dostarczając różnych spostrzeżeń.
Normalną metodą klasy jest metoda implicit dynamic , która przyjmuje instancję jako pierwszy argument.
W przeciwieństwie do tego, staticmethod nie bierze instancji jako pierwszego argumentu, więc nazywa się 'static' .
Staticmethod jest rzeczywiście taką funkcją normalną, taką samą jak te spoza definicji klasy.
Jest na szczęście zgrupowane w klasie tylko po to, aby stać bliżej, gdzie to jest stosowany, lub możesz przewijać, aby go znaleźć.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-12 11:18:19
Myślę, że podanie czysto Pythonowej wersji staticmethod
i classmethod
pomogłoby zrozumieć różnicę między nimi na poziomie języka.
Oba nie są deskryptorami danych (łatwiej byłoby je zrozumieć, jeśli najpierw znasz deskryptory).
class StaticMethod(object):
"Emulate PyStaticMethod_Type() in Objects/funcobject.c"
def __init__(self, f):
self.f = f
def __get__(self, obj, objtype=None):
return self.f
class ClassMethod(object):
"Emulate PyClassMethod_Type() in Objects/funcobject.c"
def __init__(self, f):
self.f = f
def __get__(self, obj, cls=None):
def inner(*args, **kwargs):
if cls is None:
cls = type(obj)
return self.f(cls, *args, **kwargs)
return inner
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-11-20 09:50:33
Metody klas, jak sama nazwa wskazuje, są używane do wprowadzania zmian w klasach, a nie w obiektach. Aby wprowadzić zmiany w klasach, będą one modyfikować atrybuty klasy (nie atrybuty obiektu), ponieważ w ten sposób aktualizujesz klasy. Jest to powód, dla którego metody klasy przyjmują klasę (umownie oznaczoną przez 'cls') jako pierwszy argument.
class A(object):
m=54
@classmethod
def class_method(cls):
print "m is %d" % cls.m
Metody statyczne z drugiej strony są używane do wykonywania funkcji, które nie są związane z klasą, tzn. nie będą odczytywać ani zapisywać klasy zmienne. Stąd metody statyczne nie przyjmują klas jako argumentów. Są one używane tak, że klasy mogą wykonywać funkcje, które nie są bezpośrednio związane z przeznaczeniem klasy.
class X(object):
m=54 #will not be referenced
@staticmethod
def static_method():
print "Referencing/calling a variable or function outside this class. E.g. Some global variable/function."
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-01 10:38:02
Metoda Instancji:
+
Can modyfikować stan instancji obiektu
+
Can modyfikować stan klasy
Metoda Klasowa:
-
nie można zmodyfikować stanu instancji obiektu
+
Can modyfikować stan klasy
Metoda Statyczna:
-
nie można zmodyfikować stanu instancji obiektu
-
nie można modyfikować klasy stan
class MyClass:
'''
Instance method has a mandatory first attribute self which represent the instance itself.
Instance method must be called by a instantiated instance.
'''
def method(self):
return 'instance method called', self
'''
Class method has a mandatory first attribute cls which represent the class itself.
Class method can be called by an instance or by the class directly.
Its most common using scenario is to define a factory method.
'''
@classmethod
def class_method(cls):
return 'class method called', cls
'''
Static method doesn’t have any attributes of instances or the class.
It also can be called by an instance or by the class directly.
Its most common using scenario is to define some helper or utility functions which are closely relative to the class.
'''
@staticmethod
def static_method():
return 'static method called'
obj = MyClass()
print(obj.method())
print(obj.class_method()) # MyClass.class_method()
print(obj.static_method()) # MyClass.static_method()
Wyjście:
('instance method called', <__main__.MyClass object at 0x100fb3940>)
('class method called', <class '__main__.MyClass'>)
static method called
Metoda instancyjna faktycznie mieliśmy dostęp do instancji obiektu , tak więc była to instancja poza obiektem my class, podczas gdy z metodą class mamy dostęp do samej klasy. Ale nie do żadnego z obiektów, ponieważ metoda klasy nie dba o istniejący obiekt. Można jednak zarówno wywołać metodę klasy, jak i metodę statyczną na instancji obiektu. To będzie działać to naprawdę nie robi różnicy, więc ponownie, gdy zadzwoń do statycznej metody tutaj to będzie działać i będzie wiedzieć, którą metodę chcesz zadzwonić.
Metody statyczne są używane do wykonywania niektórych zadań użytkowych, a metody klasowe są używane do metod fabrycznych. Metody fabryczne mogą zwracać obiekty klasy dla różnych przypadków użycia.
Na koniec krótki przykład dla lepszego zrozumienia:]}class Student:
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
@classmethod
def get_from_string(cls, name_string: str):
first_name, last_name = name_string.split()
if Student.validate_name(first_name) and Student.validate_name(last_name):
return cls(first_name, last_name)
else:
print('Invalid Names')
@staticmethod
def validate_name(name):
return len(name) <= 10
stackoverflow_student = Student.get_from_string('Name Surname')
print(stackoverflow_student.first_name) # Name
print(stackoverflow_student.last_name) # Surname
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-11-07 20:33:49
Jedna dość ważna praktyczna różnica występuje podczas podkategorii. Jeśli nie masz nic przeciwko, podam przykład @unutbu:
class A:
def foo(self, x):
print("executing foo(%s, %s)" % (self, x))
@classmethod
def class_foo(cls, x):
print("executing class_foo(%s, %s)" % (cls, x))
@staticmethod
def static_foo(x):
print("executing static_foo(%s)" % x)
class B(A):
pass
W class_foo
metoda wie, na której klasie jest wywoływana:
A.class_foo(1)
# => executing class_foo(<class '__main__.A'>, 1)
B.class_foo(1)
# => executing class_foo(<class '__main__.B'>, 1)
W static_foo
, nie ma możliwości określenia, czy jest wywoływana na A
czy B
:
A.static_foo(1)
# => executing static_foo(1)
B.static_foo(1)
# => executing static_foo(1)
Zauważ, że nie oznacza to, że nie możesz używać innych metod w staticmethod
, po prostu musisz odwołać się bezpośrednio do klasy, co oznacza, że staticmethods podklas nadal będzie odwoływać się do rodzica klasa:
class A:
@classmethod
def class_qux(cls, x):
print(f"executing class_qux({cls}, {x})")
@classmethod
def class_bar(cls, x):
cls.class_qux(x)
@staticmethod
def static_bar(x):
A.class_qux(x)
class B(A):
pass
A.class_bar(1)
# => executing class_qux(<class '__main__.A'>, 1)
B.class_bar(1)
# => executing class_qux(<class '__main__.B'>, 1)
A.static_bar(1)
# => executing class_qux(<class '__main__.A'>, 1)
B.static_bar(1)
# => executing class_qux(<class '__main__.A'>, 1)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-31 18:12:55
Staticmethod nie ma dostępu do atrybutów obiektu, klasy lub klas nadrzędnych w hierarchii dziedziczenia. Można ją wywołać bezpośrednio w klasie(bez tworzenia obiektu).
Classmethod nie ma dostępu do atrybutów obiektu. Może jednak uzyskać dostęp do atrybutów klasy i klas nadrzędnych w hierarchii dziedziczenia.
Można ją wywołać bezpośrednio w klasie(bez tworzenia obiektu). Jeżeli zostanie wywołana w obiekcie, to jest taka sama jak normalna metoda, która nie ma dostępu self.<attribute(s)>
i tylko Dostęp self.__class__.<attribute(s)>
.
Pomyślmy, że mamy klasę z b=2
, utworzymy obiekt i ponownie ustawimy w nim to na b=4
.
Staticmethod nie może uzyskać dostępu do niczego z poprzedniego.
Classmethod może uzyskać dostęp tylko do .b==2
, Poprzez cls.b
.
Normalna metoda może uzyskać dostęp zarówno do: .b==4
poprzez self.b
, jak i .b==2
poprzez self.__class__.b
.
Możemy podążać za stylem KISS (keep it simple, stupid): nie używaj staticmethods i classmethods, nie używaj klas bez ich tworzenia instancji, uzyskaj dostęp tylko do obiektów atrybuty self.attribute(s)
. Są języki, w których OOP jest realizowany w ten sposób i myślę, że nie jest to zły pomysł. :)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-03-02 16:01:43
Python jest wyposażony w kilka wbudowanych dekoratorów. Wielka Trójka to:
@classmethod
@staticmethod
@property
@classmethod decorator może być wywołany z instancją klasy lub bezpośrednio przez samą klasę jako jej pierwszy argument.
@staticmethod jest sposobem umieszczania funkcji w klasie (ponieważ logicznie do niej należy), jednocześnie wskazując, że nie wymaga dostępu do klasy.
Rozważmy następującą klasę:
class DecoratorTest(object):
def __init__(self):
pass
def doubler(self, x):
print("running doubler")
return x*2
@classmethod
def class_doubler(klass, x):
print("running doubler: %s" % klass)
return x*2
@staticmethod
def static_doubler(x):
print("running quad")
return x*2
decor = DecoratorTest()
Zobaczmy, jak to działa:
print(decor.doubler(5))
# running doubler
# 10
print(decor.class_doubler(5))
# running doubler: <class '__main__.DecoratorTest'>
# 10
print(DecoratorTest.class_doubler(5))
# running doubler: <class '__main__.DecoratorTest'>
# 10
print(DecoratorTest.static_doubler(5))
# running doubler
# 10
print(decor.static_doubler(5))
# running doubler
# 10
print(decor.doubler)
# <bound method DecoratorTest.doubler of <__main__.DecoratorTest object at 0x7f90e74fd150>>
print(decor.class_doubler)
# <bound method DecoratorTest.class_doubler of <class '__main__.DecoratorTest'>>
print(decor.static_doubler)
# <function DecoratorTest.static_doubler at 0x7f90e7447440>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2021-01-16 20:03:32
Tldr;
A {[0] } jest zasadniczo funkcją związaną z klasą (A co za tym idzie jej instancjami)
A classmethod
jest zasadniczo dziedzicznym staticmethod
.
Po szczegóły, zobacz doskonałe odpowiedzi innych.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2021-02-03 03:32:48
Zacznijmy od przykładowego kodu, którego użyjemy do zrozumienia obu pojęć:
class Employee:
NO_OF_EMPLOYEES = 0
def __init__(self, first_name, last_name, salary):
self.first_name = first_name
self.last_name = last_name
self.salary = salary
self.increment_employees()
def give_raise(self, amount):
self.salary += amount
@classmethod
def employee_from_full_name(cls, full_name, salary):
split_name = full_name.split(' ')
first_name = split_name[0]
last_name = split_name[1]
return cls(first_name, last_name, salary)
@classmethod
def increment_employees(cls):
cls.NO_OF_EMPLOYEES += 1
@staticmethod
def get_employee_legal_obligations_txt():
legal_obligations = """
1. An employee must complete 8 hours per working day
2. ...
"""
return legal_obligations
Metoda klasy
Metoda klasy akceptuje samą klasę jako argument niejawny i-opcjonalnie-wszelkie inne argumenty określone w definicji. Ważne jest, aby zrozumieć, że metoda klasy nie ma dostępu do instancji obiektów (tak jak robią to metody instancji). Dlatego metody klasy nie mogą być używane do zmiany stanu obiektu instancyjnego, ale zamiast tego są one w stanie zmienić stan klasy, który jest wspólny dla wszystkich instancji tej klasy. Metody klas są zazwyczaj użyteczne, gdy musimy uzyskać dostęp do samej klasy - na przykład, gdy chcemy utworzyć metodę fabryczną, czyli metodę, która tworzy instancje klasy. Innymi słowy, metody klas mogą służyć jako alternatywne konstruktory.
W naszym przykładowym kodzie, instancja Employee
może być skonstruowana przez podanie trzech argumentów; first_name
, last_name
oraz salary
.
employee_1 = Employee('Andrew', 'Brown', 85000)
print(employee_1.first_name)
print(employee_1.salary)
'Andrew'
85000
Załóżmy teraz, że istnieje szansa, że imię pracownika może być podane w jednym polu, w którym imię i nazwisko są oddzielone białą spacją. W tym przypadku możemy użyć naszej metody klasowej o nazwie employee_from_full_name
, która akceptuje łącznie trzy argumenty. Pierwszą z nich jest sama klasa, która jest domyślnym argumentem, co oznacza, że nie będzie ona podawana podczas wywoływania metody - Python automatycznie zrobi to za nas:
employee_2 = Employee.employee_from_full_name('John Black', 95000)
print(employee_2.first_name)
print(employee_2.salary)
'John'
95000
Zauważ, że możliwe jest również wywołanie employee_from_full_name
z instancji obiektu, chociaż w tym kontekście nie ma to większego sensu:
employee_1 = Employee('Andrew', 'Brown', 85000)
employee_2 = employee_1.employee_from_full_name('John Black', 95000)
Innym powodem, dla którego możemy chcieć utworzyć metodę klasy, jest konieczność zmiany stanu klasy. W naszym przykładzie zmienna klasy NO_OF_EMPLOYEES
śledzi liczbę pracowników aktualnie pracujących w firmie. Metoda ta jest wywoływana za każdym razem, gdy powstaje nowa instancja pracownika i aktualizuje liczbę odpowiednio:
employee_1 = Employee('Andrew', 'Brown', 85000)
print(f'Number of employees: {Employee.NO_OF_EMPLOYEES}')
employee_2 = Employee.employee_from_full_name('John Black', 95000)
print(f'Number of employees: {Employee.NO_OF_EMPLOYEES}')
Number of employees: 1
Number of employees: 2
Metody statyczne
Z drugiej strony, w metodach statycznych ani instancja (tj. self
), ani sama klasa (tj. cls
) nie są przekazywane jako argument niejawny. Oznacza to, że takie metody nie są w stanie uzyskać dostępu do samej klasy lub jej instancji.
Teraz można argumentować, że metody statyczne nie są użyteczne w kontekście klas, ponieważ mogą być również umieszczane w modułach pomocniczych zamiast dodawać je jako członków klasy. W obiekcie programowanie zorientowane, ważne jest, aby uporządkować swoje klasy w logiczne kawałki i dlatego statyczne metody są bardzo przydatne, gdy musimy dodać metodę pod klasą po prostu dlatego, że logicznie należy do klasy.
W naszym przykładzie metoda statyczna o nazwie get_employee_legal_obligations_txt
po prostu zwraca łańcuch zawierający zobowiązania prawne każdego pracownika firmy. Funkcja ta nie oddziałuje z samą klasą ani z żadną instancją. Mógł być umieszczony w innym pomocniku moduł ma jednak znaczenie tylko dla tej klasy i dlatego musimy umieścić go w klasie pracownika.
Statyczna metoda może być dostępna bezpośrednio z samej klasy
print(Employee.get_employee_legal_obligations_txt())
1. An employee must complete 8 hours per working day
2. ...
Lub z instancji klasy:
employee_1 = Employee('Andrew', 'Brown', 85000)
print(employee_1.get_employee_legal_obligations_txt())
1. An employee must complete 8 hours per working day
2. ...
Referencje
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2021-02-04 16:10:50