Python отличие staticmethod от classmethod

Методы класса (classmethod) и статические методы (staticmethod)

Мы продолжаем тему методов в ООП. До сих пор мы с вами определяли методы просто как функции внутри класса, например:

class Vector: def __init__(self, x, y): self.x = x self.y = y def get_coord(self): return self.x, self.y

И у каждого такого метода, как правило, первым идет параметр self – ссылка на экземпляр класса, из которого метод был вызван:

v = Vector(10, 20) coord = v.get_coord() print(coord)

В данном случае, при вызове метода get_coord () параметр self будет вести на объект v класса Vector. Об этом мы с вами уже говорили. Также отмечали, что при вызове такого метода напрямую из класса нужно явно указывать первый аргумент self:

Так вот, в Python помимо таких «стандартных» методов можно задавать методы уровня класса и статические методы с помощью встроенных декораторов:

@classmethod и @staticmethod

Давайте я поясню на простом примере, что они значат. Добавим в наш класс Vector два атрибута:

class Vector: MIN_COORD = 0 MAX_COORD = 100 .
@classmethod def validate(cls, arg): return cls.MIN_COORD  arg  cls.MAX_COORD

который проверяет, попадает ли значение arg в диапазон [MIN_COORD; MAX_COORD]. Обратите внимание, у методов класса (когда мы используем декоратор classmethod) первым параметром идет cls – ссылка на класс, а не self – ссылка на объект класса. Это означает, что данный метод может обращаться только к атрибутам текущего класса, но не к локальным свойствам его экземпляров. Мало того, этот метод можно теперь напрямую вызывать из класса, не передавая ссылку на экземпляр, как это было при вызове обычных методов через класс:

res = Vector.validate(5) print(res)

Здесь пользователь класса Vector может совершенно спокойно вызывать метод validate(), не создавая никаких объектов. Но «платой» за это является ограниченность метода: он может работать только с атрибутами класса, но не объекта, что, в общем то, естественно, так как у него изначально нет ссылки на объект. Во всем остальном этот метод работает абсолютно также, как и любой другой метод, объявленный в классе.

Давайте мы им воспользуемся и вызовем внутри класса для проверки корректности координат x, y:

def __init__(self, x, y): self.x = self.y = 0 if Vector.validate(x) and Vector.validate(y): self.x = x self.y = y

Обратите внимание, мы здесь обращаемся к методу класса через пространство имен Vector. Но также можем прописать и self:

if self.validate(x) and self.validate(y):

В этом случае интерпретатор Python сам подставит нужный класс в параметр cls данного метода, так как экземпляр содержит информацию о классе, от которого был образован.

Наконец, третий тип методов – статические методы, определяются декоратором @staticmethod. Это методы, которые не имеют доступа ни к атрибутам класса, ни к атрибутам его экземпляров, то есть, некая независимая, самостоятельная функция, объявленная внутри класса. Обычно, это делают для удобства, т.к. их функционал так или иначе связан с тематикой класса.

Например, в нашем классе Vector можно объявить такой статический метод, который бы вычислял квадратичную норму вектора (длину вектора в квадрате):

@staticmethod def norm2(x, y): return x*x + y*y

Здесь нет никаких скрытых параметров, которые бы автоматически заполнялись интерпретатором языка. Только те, что мы прописываем сами. Я указал два параметра x, y, по которым вычисляется квадрат длины радиус-вектора. То есть, это некая вспомогательная, сервисная функция, связанная с векторами, для вычисления квадратичной нормы любого радиус-вектора. Воспользоваться этим методом можно как вне класса:

def __init__(self, x, y): self.x = self.y = 0 if self.validate(x) and self.validate(y): self.x = x self.y = y print(Vector.norm2(self.x, self.y))

Либо, также обратиться к этому методу через self:

print(self.norm2(self.x, self.y))

Подведем итог различных типов методов в классах. Обычные методы, как правило, вызываются из экземпляров классов и работают с атрибутами экземпляров и атрибутами классов. Методы классов обычно вызываются через класс, реже через его экземпляры и имеют доступ только к атрибутам самого класса, в котором объявлены. Наконец, статические методы – это совершенно изолированные функции, которые работают только с параметрами, прописанными в ней самой и не имеют доступа к атрибутам класса или его экземпляров.

Поэтому, если вам нужен метод, который работает с атрибутами объектов класса, то это обычное определение функций внутри класса с первым параметром self. Если метод работает только с атрибутами класса, то возможно, имеет смысл его определить как метод класса и тогда можно будет вызывать без ссылки на объект этого класса. Третий тип, статические методы часто определяют как вспомогательные, сервисные, связанные с логикой работы самого класса.

Вот общее руководство по выбору этих методов. Надеюсь, из этого занятия вам стало понятно, что такое методы класса и статические методы, а также для чего имеет смысл их использовать.

Видео по теме

Концепция ООП простыми словами

Источник

Разница между @staticmethod и @classmethod в Python

Когда разработчики начинают использовать Python, они часто сталкиваются с декораторами @staticmethod и @classmethod. Оба этих декоратора служат для определения методов, которые не работают с экземплярами класса, но все же как-то связаны с классом.

Пример

Рассмотрим простой класс «Кошка» с методом «мяукать», который определен как статический метод.

class Cat: @staticmethod def meow(): return "Мяу!"

Так как «мяукать» является статическим методом, его можно вызывать без создания экземпляра класса.

print(Cat.meow()) # Выводит "Мяу!"

@staticmethod

Статический метод в Python — это метод, который принадлежит классу, а не экземпляру класса. Он не может модифицировать состояние класса или его экземпляров. Статические методы объявляются с помощью декоратора @staticmethod.

Преимущество статических методов в том, что они могут быть вызваны даже если нет объекта класса. Они также могут быть переопределены в подклассах.

@classmethod

Метод класса в Python — это метод, который привязан к классу, а не к его экземпляру. Он может изменять состояние класса, но не может изменять состояние конкретного экземпляра класса. Методы класса объявляются с помощью декоратора @classmethod.

Методы класса принимают ссылку на класс, который вызывает метод, в качестве первого аргумента (обычно именуемого cls). Их основное преимущество в том, что они могут быть наследованы и переопределены в подклассах.

Вывод

В целом, @staticmethod и @classmethod в Python служат для определения методов, которые не требуют доступа к экземпляру класса. Они оба полезны в разных ситуациях, и выбор между ними зависит от конкретных потребностей вашего кода. Если вам нужно работать с классом, а не с его экземпляром, используйте @classmethod. Если вам не нужен доступ ни к классу, ни к его экземплярам, используйте @staticmethod.

Источник

Объяснение @classmethod и @staticmethod в Python

Для новичков, изучающих объектно-ориентированное программирование на Python, очень важно хорошо разбираться в таких понятиях как classmethod и staticmethod для написания более оптимизированного и повторно используемого кода.

Кроме того, даже опытные программисты, работающие на разных языках, часто путают эти два понятия.

В этой статье мы разберем что это такое и какая между ними разница.

staticmethod в Python

@staticmethod – используется для создания метода, который ничего не знает о классе или экземпляре, через который он был вызван. Он просто получает переданные аргументы, без неявного первого аргумента, и его определение неизменяемо через наследование.

Проще говоря, @staticmethod – это вроде обычной функции, определенной внутри класса, которая не имеет доступа к экземпляру, поэтому ее можно вызывать без создания экземпляра класса.

class ClassName: @staticmethod def method_name(arg1, arg2, . ): .

Здесь мы используем декоратор @staticmethod для определения статического метода в Python. Вы можете заметить, что статический метод не принимает self в качестве первого аргумента для метода.

А теперь посмотрим на пример использования.

class Myclass(): @staticmethod def staticmethod(): print('static method called')

Как мы уже говорили, мы можем получить доступ к статическому методу класса без создания экземпляра.

Хотя вызов метода из экземпляра класса тоже возможен.

my_obj = Myclass() my_obj.staticmethod()

Отлично, но когда полезны статические методы?

Статический метод помогает в достижении инкапсуляции в классе, поскольку он не знает о состоянии текущего экземпляра. Кроме того, статические методы делают код более читабельным и повторно используемым, а также более удобным для импорта по сравнению с обычными функциями, поскольку каждую функцию не нужно отдельно импортировать.

class Person(): @staticmethod def is_adult(age): if age > 18: return True else: return False

В приведенном выше примере мы можем проверить, является ли человек взрослым, без инициирование создания экземпляра.

Classmethod в Python

@classmethod – это метод, который получает класс в качестве неявного первого аргумента, точно так же, как обычный метод экземпляра получает экземпляр. Это означает, что вы можете использовать класс и его свойства внутри этого метода, а не конкретного экземпляра.

Проще говоря, @classmethod – это обычный метод класса, имеющий доступ ко всем атрибутам класса, через который он был вызван. Следовательно, classmethod – это метод, который привязан к классу, а не к экземпляру класса.

class Class: @classmethod def method(cls, arg1, arg2, . ): .

В данному случае декоратор @classmethod используется для создания методов класса, и cls должен быть первым аргументом каждого метода класса.

class MyClass: @classmethod def classmethod(cls): print('Class method called')

Функцию classmethod также можно вызывать без создания экземпляра класса, но его определение следует за подклассом, а не за родительским классом, через наследование.

Когда использовать classmethod?

@classmethod используется, когда вам нужно получить методы, не относящиеся к какому-либо конкретному экземпляру, но тем не менее, каким-то образом привязанные к классу. Самое интересное в них то, что их можно переопределить дочерними классами.

Поэтому, если вы хотите получить доступ к свойству класса в целом, а не к свойству конкретного экземпляра этого класса, используйте classmethod.

class MyClass(): TOTAL_OBJECTS=0 def __init__(self): MyClass.TOTAL_OBJECTS = MyClass.TOTAL_OBJECTS+1 @classmethod def total_objects(cls): print("Total objects: ",cls.TOTAL_OBJECTS) # Создаем объекты my_obj1 = MyClass() my_obj2 = MyClass() my_obj3 = MyClass() # Вызываем classmethod MyClass.total_objects()

Теперь, если мы унаследуем этот класс в дочерний класс и объявим там переменную TOTAL_OBJECTS и вызовем метод класса из дочернего класса, он вернет общее количество объектов для дочернего класса.

class MyClass(): TOTAL_OBJECTS=0 def __init__(self): MyClass.TOTAL_OBJECTS = MyClass.TOTAL_OBJECTS+1 @classmethod def total_objects(cls): print("Total objects: ", cls.TOTAL_OBJECTS) # Создаем объекты родительского класса my_obj1 = MyClass() my_obj2 = MyClass() # Создаем дочерний класс class ChildClass(MyClass): TOTAL_OBJECTS=0 pass ChildClass.total_objects()

Заключение

@classmethod используется в суперклассе для определения того, как метод должен вести себя, когда он вызывается разными дочерними классами. В то время как @staticmethod используется, когда мы хотим вернуть одно и то же, независимо от вызываемого дочернего класса.

Также имейте в виду, что вызов @classmethod включает в себя дополнительное выделение памяти, чего нет при вызове @staticmethod или обычной функции.

Источник

Читайте также:  Table with css only
Оцените статью