Особые типы методов класса staticmethod и classmethod
Особые декораторы классов
Читая чужой код, вы иногда будете сталкиваться с новыми и необычными вещами. С одной из таких мы разберемся в этой лекции. Возможно, вам уже попадался такой код:
class SomeClass:
def do(self): # 🟢 обычный метод, доступный экземплярам класса
# SomeClass == self.__class__ == True
return 'Вызван обычный метод', self
@classmethod # 🟢 метод класса
def class_do(cls):
return 'Вызван метод класса class method', cls
@staticmethod # 🟢 статический метод
def static_do():
return 'Вызван статический метод static method'
Зачем программисты используют такой синтаксис и чем обычные методы, доступные экземплярам класса, отличаются от статических и методов класса? И почему сделаны такие особенные декораторы?
Методы экземпляра класса
Первый метод класса выглядит и ведет себя вполне обычно. Он получает на вход объект self и ведет себя вполне обычно. Он доступен в экземпляре класса (объекте, который получится из этого класса). Он получает только один параметр и это ссылка на экземпляр класса.
Поскольку мы уже знакомы с магическими методами, то не лишним будет добавить, что, обратившись к свойству self.__class__ вы можете получить доступ к объекту SomeClass. Например:
some = SomeClass()
some.__class__ == SomeClass # True
Экземпляр класса может через свойство self.__class__ получать доступ к объекту класса.
Методы класса
Декоратор @classmethod уже имеет другую сигнатуру, вместо self, он получает cls. Который, является самим классом. То есть в данном случае SomeClass. Этот декоратор делает доступным функцию доступной и в экземпляре класса и в самом классе. То есть все варианты будут работать SomeClass.class_do(), SomeClass().class_do() и some.class_do().
Метод класса явно получает доступ к классу в первом параметре.
Это удобный способ организовать код таким образом, чтобы у вас была функция, которая находится в пространстве имен класса, но явно не работает с экземплярами класса. Например, так можно сделать фабрику класса, функцию, которая позволяет проще создавать объекты с пред заданными свойствами:
class Contact:
def __init__(self, name, phone, favorite=None):
self.name = name
self.phone = phone
self.favorite = favorite
@classmethod
def new_fav(cls, name, phone):
return cls(name, phone, favorite=True)
obi = Contact.new_fav('Obi-Wan', '+5 (555) 555-55-55')
Статические методы
Данные методы не имеют доступа ни к классу, ни к объектам, которые из него получаются. В данном случае имя класса выступает только в качестве пространства имен. По сути, это то же самое, как если бы функция была определена рядом с классом и не имела к нему отношения. И служит только для удобства организации кода.
Декоратор @staticmethod позволяет избежать необходимости указывать self в качестве первого параметра. И метод и выглядит, и ведет себя как независимая функция.