PorównaniePorównania

@staticmethod vs @classmethod

@staticmethod działa jak zwykła funkcja bez automatycznego argumentu, a @classmethod dostaje klasę jako cls i zwykle służy jako alternatywny konstruktor.

Na tej stronie

Porównanie w tabeli

#

Przykład

#
Python
class Grade:
    def __init__(self, points):
        self.points = points

    @staticmethod
    def is_valid(points):
        return 0 <= points <= 100

    @classmethod
    def from_percent(cls, percent, maximum):
        return cls(round(percent / 100 * maximum))

print(Grade.is_valid(120))
grade = Grade.from_percent(75, 80)
print(grade.points)
Wynikzapisany wynik, możesz go sprawdzić
False
60

Definicja i zastosowanie

#

Oba dekoratory definiują metodę, którą wywołasz przez nazwę klasy, bez tworzenia obiektu. Żadna z nich nie dostaje self, więc nie ma dostępu do danych konkretnego obiektu.

Różnią się pierwszym argumentem. Metoda statyczna nie dostaje nic automatycznie: to zwykła funkcja, tylko umieszczona wewnątrz klasy dla porządku. Metoda klasy dostaje jako pierwszy argument samą klasę (cls), dzięki czemu może odwołać się do jej atrybutów i, co ważniejsze, utworzyć obiekt przez cls(...). W klasie pochodnej cls wskazuje na tę klasę pochodną, a nie na klasę, w której metodę zapisano.

Użyj @staticmethod dla funkcji pomocniczej, która logicznie należy do klasy, np. walidacji albo przeliczenia, ale nie potrzebuje ani obiektu, ani klasy. Użyj @classmethod, gdy metoda ma tworzyć obiekty z danych w innym formacie niż zwykły konstruktor, np. from_text() albo from_dict(), albo gdy potrzebuje dostępu do atrybutów klasy, takich jak wspólny licznik.

Składnia

#
Składnia
class Nazwa:
    @staticmethod
    def metoda(arg):
        ...

    @classmethod
    def inna(cls, arg):
        return cls(arg)

Więcej przykładów

#
cls w klasie pochodnej tworzy właściwy typ
Python
class Task:
    def __init__(self, number):
        self.number = number

    @classmethod
    def from_code(cls, code):
        return cls(code.removeprefix("zadanie_"))

class Quiz(Task):
    pass

task = Quiz.from_code("zadanie_7_3")
print(type(task).__name__, task.number)
Wynikzapisany wynik, możesz go sprawdzić
Quiz 7_3
Metoda statyczna nie widzi klasy ani obiektu
Python
class Course:
    count = 0

    def __init__(self, title):
        self.title = title
        Course.count += 1

    @staticmethod
    def slugify(title):
        return title.lower().replace(" ", "-")

python_course = Course("Python od zera")
print(Course.slugify(python_course.title))
print(Course.count)
Wynikzapisany wynik, możesz go sprawdzić
python-od-zera
1

Dobre praktyki

#
  • Jeśli metoda nie używa ani self, ani cls, prawdopodobnie powinna być statyczna albo w ogóle poza klasą.
  • Nazywaj alternatywne konstruktory z przedrostkiem from_, np. from_json(), from_row(). To konwencja znana z biblioteki standardowej.
  • W metodzie klasy twórz obiekty przez cls(...), a nie przez nazwę klasy wpisaną na sztywno, żeby działała poprawnie też w klasach pochodnych.

Powiązane hasła

#

Widzisz błąd albo brakuje przykładu? Napisz do nas.