Różnica między staticmethod i classmethod

Jaka jest różnica między funkcją zdobioną @staticmethod i jeden ozdobiony @classmethod?

Author: Anand Tripathi, 2008-09-25

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>
 3333
Author: unutbu,
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
>>> 
 834
Author: Thomas Wouters,
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.

 163
Author: Terence Simpson,
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:

@classmethod

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.

@staticmethod

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.

 110
Author: Chris B.,
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).

 86
Author: Tom Neyland,
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
 81
Author: Du D.,
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.

Na przykład, jest to instancja ciągu znaków:
', '

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.

 60
Author: Aaron Hall,
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")
 48
Author: 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.

 36
Author: Nathan Tregillus,
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
    
 34
Author: Laxmi,
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.

 32
Author: Jens Timmerman,
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 Javy Math 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)

 26
Author: blue_note,
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',)
 25
Author: Selva,
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'>
 24
Author: Armin Ronacher,
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
 21
Author: zangw,
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.

 13
Author: Adam Parkin,
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ą.

 8
Author: Rizwan Mumtaz,
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

 7
Author: vijay,
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 !

 6
Author: Nicolae Petridean,
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.

 6
Author: David Schumann,
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)
'''
"""
 5
Author: Michael Swartz,
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źć.

 3
Author: Calculus,
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
 3
Author: Jacky1205,
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."
 2
Author: Tushar Vazirani,
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
 2
Author: Milovan Tomašević,
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)
 1
Author: Ale,
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ł. :)

 0
Author: mirek,
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> 
 0
Author: illuminates,
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.

 0
Author: Sia,
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

 0
Author: Giorgos Myrianthous,
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