@classmethod

Metoda, która zamiast obiektu dostaje klasę (cls). Najczęściej służy jako alternatywny konstruktor.

Na tej stronie

Przykład

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

    @classmethod
    def from_text(cls, text):
        name, points = text.split(";")
        return cls(name, int(points))

    @classmethod
    def from_dict(cls, data):
        return cls(data["name"], data.get("points", 0))

ania = Student.from_text("Ania;250")
kuba = Student.from_dict({"name": "Kuba"})

print(ania.name, ania.points)
print(kuba.name, kuba.points)
Wynikzapisany wynik, możesz go sprawdzić
Ania 250
Kuba 0

Definicja i zastosowanie

#

Dekorator @classmethod tworzy metodę klasy. Jako pierwszy argument dostaje ona nie obiekt, tylko samą klasę, zwyczajowo nazwaną cls. Wywołuje się ją zwykle przez nazwę klasy, np. Student.from_text("Ania;250").

Najczęstsze zastosowanie to alternatywne konstruktory, czyli metody tworzące obiekt z danych w innym formacie: z napisu, słownika albo wiersza pliku. Metoda przygotowuje argumenty i na końcu wywołuje cls(...). Tak działają wbudowane dict.fromkeys() czy datetime.fromisoformat().

Ponieważ cls wskazuje klasę, na której metodę wywołano, w klasie pochodnej cls(...) utworzy obiekt klasy pochodnej, a nie bazowej. To przewaga nad metodą statyczną z nazwą klasy wpisaną na sztywno. Metody klasy mają też wygodny dostęp do atrybutów klasy, np. wspólnych liczników czy ustawień.

Składnia

#
Składnia
class Nazwa:
    @classmethod
    def metoda(cls, argumenty):
        return cls(...)

Nazwa.metoda(argumenty)

Więcej przykładów

#
cls w klasie pochodnej
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
Dostęp do atrybutów klasy
Python
class Player:
    online = 0

    def __init__(self, nick):
        self.nick = nick
        Player.online += 1

    @classmethod
    def status(cls):
        return f"Graczy online: {cls.online}"

Player("ania_dev")
Player("kuba99")
print(Player.status())
Wynikzapisany wynik, możesz go sprawdzić
Graczy online: 2

Dobre praktyki

#
  • Nazwy alternatywnych konstruktorów zaczynaj od from_, np. from_json() albo from_row(). To konwencja znana z biblioteki standardowej.
  • W metodzie klasy twórz obiekty przez cls(...), a nie przez nazwę klasy. Wtedy działa ona poprawnie także w klasach pochodnych.
  • Jeśli metoda nie potrzebuje ani obiektu, ani klasy, wystarczy @staticmethod.

Powiązane hasła

#

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