Методы класса и статические методы
Мы продолжаем тему методов в ООП. До сих пор мы с вами определяли методы просто как функции внутри класса, например:
И у каждого такого метода, как правило, первым идет параметр self
– ссылка на экземпляр класса, из которого метод был вызван:
В данном случае, при вызове метода get_coord()
параметр self
будет вести на объект v класса Vector
. Об этом мы с вами уже говорили. Также отмечали, что при вызове такого метода напрямую из класса нужно явно указывать первый аргумент self
:
Так вот, в Python помимо таких «стандартных» методов можно задавать методы уровня класса и статические методы с помощью встроенных декораторов.
@classmethod и @staticmethod
Давайте я поясню на простом примере, что они значат. Добавим в наш класс Vector два атрибута:
А также метод класса:
который проверяет, попадает ли значение arg
в диапазон [MIN_COORD; MAX_COORD]
. Обратите внимание, у методов класса (когда мы используем декоратор classmethod
) первым параметром идет cls
– ссылка на класс, а не self
– ссылка на объект класса. Это означает, что данный метод может обращаться только к атрибутам текущего класса, но не к локальным свойствам его экземпляров. Мало того, этот метод можно теперь напрямую вызывать из класса, не передавая ссылку на экземпляр, как это было при вызове обычных методов через класс:
Здесь пользователь класса Vector
может совершенно спокойно вызывать метод validate()
, не создавая никаких объектов. Но «платой» за это является ограниченность метода: он может работать только с атрибутами класса, но не объекта, что, в общем то, естественно, так как у него изначально нет ссылки на объект. Во всем остальном этот метод работает абсолютно также, как и любой другой метод, объявленный в классе.
Давайте мы им воспользуемся и вызовем внутри класса для проверки корректности координат x
, y
:
Обратите внимание, мы здесь обращаемся к методу класса через пространство имен Vector
. Но также можем прописать и self
:
В этом случае интерпретатор Python сам подставит нужный класс в параметр cls
данного метода, так как экземпляр содержит информацию о классе, от которого был образован.
Наконец, третий тип методов – статические методы, определяются декоратором @staticmethod
. Это методы, которые не имеют доступа ни к атрибутам класса, ни к атрибутам его экземпляров, то есть, некая независимая, самостоятельная функция, объявленная внутри класса. Обычно, это делают для удобства, т.к. их функционал так или иначе связан с тематикой класса.
Например, в нашем классе Vector
можно объявить такой статический метод, который бы вычислял квадратичную норму вектора (длину вектора в квадрате):
Здесь нет никаких скрытых параметров, которые бы автоматически заполнялись интерпретатором языка. Только те, что мы прописываем сами. Мы указали два параметра x
, y
, по которым вычисляется квадрат длины радиус-вектора. То есть, это некая вспомогательная, сервисная функция, связанная с векторами, для вычисления квадратичной нормы любого радиус-вектора. Воспользоваться этим методом можно как вне класса:
Так и внутри класса:
Либо, также обратиться к этому методу через self
:
Подведем итог различных типов методов в классе:
обычные методы, как правило, вызываются из экземпляров классов и работают с атрибутами экземпляров и атрибутами классов;
методы классов обычно вызываются через класс, реже через его экземпляры и имеют доступ только к атрибутам самого класса, в котором объявлены;
статические методы – это совершенно изолированные функции, которые работают только с параметрами, прописанными в ней самой и не имеют доступа к атрибутам класса или его экземпляров.
Поэтому, если вам нужен метод, который работает с атрибутами объектов класса, то это обычное определение функций внутри класса с первым параметром self
. Если метод работает только с атрибутами класса, то возможно, имеет смысл его определить как метод класса и тогда можно будет вызывать без ссылки на объект этого класса. Третий тип, статические методы часто определяют как вспомогательные, сервисные, связанные с логикой работы самого класса.