Типы методов класса
Python существуют три типа методов внутри классов: обычные методы; статические методы, методы класса
Обычные методы
Это такие методы, которые определяются как обычные функции внутри класса. Мы их приводили в качестве примера в первом конспекте по ООП. Они не имеют специального префикса или суффикса в своем имени. Используются для выполнения задач, связанных с конкретным классом и его экземплярами. Как правило принимают self в качестве первого аргумента и могут обращаться к атрибутам экземпляра класса и атрибутам самого класса. Напомню, что self
– это ссылка на экземпляр класса, для которого вызывается метод.
class MyClass:
def conventional_method(self):
"""Обычный метод внутри класса"""
print("Это обычный метод внутри класса")
ob= MyClass()
ob.conventional_method()
Метод, в котором есть параметр self
, указывающий на определенный экземпляр класса, еще называют привязанным методом (bound method) – это это особый вид функции, связанный с определенным экземпляром класса. Когда вы вызываете привязанный метод, он автоматически передает экземпляр класса в качестве первого аргумента. Такой подход упрощает использование методов экземпляров класса и делает код более читаемым.
Также мы можем вызвать метод непосредственно через класс, в вышеприведенном примере MyClass: MyClass.conventional_method(object1)
, однако в скобках надо обязательно указать ссылку на экземпляр класса, потому что привязанный метод нельзя вызывать без аргументов как метод класса.
Методы класса
Методы класса – это те методы, которые определены внутри класса и имеют доступ ко всем переменным и методам класса, которые определены в нем же. Они вызываются с помощью имени класса и используются для операций, не связанных с изменением текущего состояния объекта. Они предназначены для работы с классом как с целой группой объектов, а не с отдельными объектами.
Метод класса принимает первым параметром класс, именуемый cls
, вместо экземпляра класса self
. Для определения метода класса используется декоратор @classmethod
. Метод класса может быть вызван как на экземпляре класса (реже), так и на самом классе.
class MyClass:
@classmethod
def class_method(cls):
"""Метод класса"""
print("Это метод класса")
# Вызов метода класса на классе
MyClass.class_method()
# Вызов метода класса на экземпляре класса
ob = MyClass()
ob.class_method()
Метод имеет доступ только к атрибутам самого класса, в котором объявлен. На практике методы уровня класса используются для операций, которые не зависят от конкретного экземпляра класса, но требуют доступа к атрибутам и методам класса.
Например: для подсчета количества созданных объектов класса; для форматирования строк; для валидации данных, передаваемых в конструктор класса; для настройки значений по умолчанию; для доступа к статическим данным класса; для создания экземпляров класса с различными параметрами по умолчанию и др.
Статические методы
Статический метод в Python определяется с использованием декоратора @staticmethod
. В отличие от других методов не принимает экземпляр класса или класс в качестве первого параметра. Статический метод используется, когда не требуется доступа к атрибутам экземпляра или класса, и может быть вызван независимо от создания экземпляра класса. По своей сути это изолированные функции, которые работают только с параметрами, прописанными в ней самой. Cтатические методы не могут получить доступ ни к атрибутам экземпляра объекта, ни к атрибутам класса. Статические методы могут быть полезны для группировки функций внутри класса, которые логически связаны с классом, но не требуют доступа к его состоянию.
class MyClass:
@staticmethod
def static_method():
print("Это статический метод")
# Вызов статического метода на классе
MyClass.static_method()
# Вызов статического метода на экземпляре класса
ob = MyClass()
ob.static_method()
Ограничение доступа к данным и методам класса
Приватные методы
В Python нет строгого понятия “приватных методов”, как в некоторых других языках программирования, но существует соглашение:
методы и атрибуты, начинающиеся с двойного подчеркивания
__
, считаются “приватными” и не должны вызываться извне класса.
Двойное подчеркивание в начале имени метода запускает механизм защиты метода от случайного переопределения в подклассах. Об этом было сказано в первой части конспекта по ООП в разделе Инкапсуляция. Вот пример “приватного” метода в Python:
class MyClass:
def __init__(self, value):
self.__value = value
def __private_method(self):
return self.__value * 2
obj = MyClass(10)
# Вызов "приватного" метода вызовет ошибку
print(obj.__private_method())
Однако на самом деле в Python эти методы не являются полностью приватными, и их по-прежнему можно вызывать извне класса. Например так:
print(obj._MyClass__private_method())
. Однако делать так крайне не рекомендуется.
Сеттеры и геттеры
Сеттеры (setters) и геттеры (getters) – это методы, которые используются для установки (изменения) и получения значений приватных атрибутов объекта соответственно.
Такие методы обеспечивают контролируемый доступ к атрибутам объекта, что позволяет скрыть сложную логику обработки данных от пользователя объекта. Фактически это альтернатива прямому доступу к атрибутам объекта через точку. Сеттеры и геттеры позволяют также выполнять дополнительные проверки и изменения, когда мы устанавливаем или получаем значения атрибутов. Вот пример использования сеттера и геттера:
class Person:
def __init__(self, name):
self._name = name # приватный атрибут
# Геттер для получения значения атрибута
def get_name(self):
return self._name
# Сеттер для установки значения атрибута
def set_name(self, new_name):
if isinstance(new_name, str):
self._name = new_name
else:
print("Имя должно быть строкой.")
# Создание объекта класса Person
person = Person("Alice")
# Получение значения атрибута с помощью геттера
print(person.get_name()) # Вывод: Alice
# Установка нового значения атрибута с помощью сеттера
person.set_name("Bob")
# Проверка нового значения атрибута
print(person.get_name()) # Вывод: Bob
# Попытка установить недопустимое значение
person.set_name(123) # Вывод: Имя должно быть строкой.
мы можем сделать этот код более удобным, создав интерфейс для работы с приватными атрибутами создав объекты-свойства с помощью декоратора @property.
Декоратор
@property
в Python используется для определения метода в классе, который может быть доступен как атрибут. Это позволяет использовать более интуитивный и удобный способ доступа к определенным значениям, а не вызывать метод с круглыми скобками каждый раз.
class Person:
def __init__(self, name):
self.name = name # приватный атрибут
@property
def name(self):
return self.__name
@name.setter
def name(self, new_name):
if isinstance(new_name, str):
self.__name = new_name
else:
print("Имя должно быть строкой.")
@name.deleter
def name(self):
del self.__name
# Создание объекта класса Person
person = Person("Alice")
print(person.__dict__) # Вывод: {'_Person__name': 'Alice'}
# Получение значения атрибута с помощью свойства name
print(person.name) # Вывод: Alice
# Установка нового значения атрибута с помощью свойства name
person.name = "Bob"
# Проверка нового значения атрибута
print(person.name) # Вывод: Bob
# Попытка установить недопустимое значение
person.name = 123 # Вывод: Имя должно быть строкой.
# удаляем с помощью делитера приватный атрибут __name
del person.name
print(person.__dict__) # Вывод: {}
по сути мы создали интерфейс взаимодействия объект-свойство name.
Магические методы классов
Магические методы – это специальные методы, которые начинаются и заканчиваются двойным подчеркиванием (например, __init__
, __str__
, __add__
). Они позволяют определить поведение объектов в определенных ситуациях, таких как инициализация объекта, преобразование объекта в строку, выполнение операций сложения и другие.
Например, метод __init__
используется для инициализации нового объекта, метод __str__
определяет строковое представление объекта, а метод __add__
позволяет определить поведение оператора сложения для объектов.
Использование магических методов позволяет объектам вести себя как встроенные типы данных в Python и управлять их поведением в различных контекстах.
Магические методы при работе с атрибутами
Они позволяют реализовывать механизм получения, установки и удаления атрибутов динамически.
__setattr__
– Это специальный метод, который вызывается при любой попытке установить значение атрибута. Вы можете использовать его для реализации пользовательского поведения при установке атрибутов. Например для проверки или валидации данных, прежде чем установить их как атрибуты объекта; для преобразования данных, когда нужно автоматически преобразовывать значения перед их установкой и др.
пример для преобразования значения атрибута в верхний регистр:
class Cities:
def __setattr__(self, attr, value):
if attr == "name_capitals_letters":
value = value.upper()
object.__setattr__(self, attr, value)
capital = Cities()
capital.name_capitals_letters = "москва"
print(capital.name_capitals_letters) # Выведет "МОСКВА"
__getattribute__
– Это специальный метод, который вызывается при любой попытке получить значение атрибута объекта. Он позволяет вам перехватывать все запросы на доступ к атрибутам и применять пользовательскую логику. Вы реализовать пользовательское поведение при получении атрибутов. Например для реализации свойств, то есть атрибутов, которые вычисляются динамически при каждом обращении; для фильтрация доступа к определенным атрибутам; для логирования факта доступа к атрибутам и т.д.
пример использования (возвращаем название города в верхнем регистре)
class City_name:
def __init__(self, name):
self.name = name
def __getattribute__(self, attr):
if attr == "capital_letters":
return object.__getattribute__(self, "name").upper()
return object.__getattribute__(self, attr)
name_object = City_name("Ярославль")
print(name_object.capital_letters) # Выведет "ЯРОСЛАВЛЬ"
print(name_object.__dict__) # {'name': 'Ярославль'}
__getattr__
– Это специальный метод, который вызывается, когда попытка получить значение атрибута, которого не существует в объекте. Вы можете использовать его для реализации пользовательского поведения при получении атрибутов. Этот метод используют например для динамического создания атрибутов или для обработки обращения к несуществующим атрибутам и при этом необходимо возвращать какое-то значение или вызывать определенную логику и др.
пример, в котором при обращении к несуществующему атрибуту мы возвращаем False вместо ошибки
class Cities:
def __getattr__(self, item):
return False
capital = Cities()
print(capital.х) # Возвращает False вместо ошибки
__delattr__
– Это специальный метод, который вызывается, когда попытка удалить атрибут. Обратите внимание, что не всегда требуется определять метод __delattr__
, так как Python обычно обрабатывает удаление атрибутов по умолчанию. Однако, если вам нужно выполнить дополнительную логику при удалении атрибутов, вы можете явно определить метод __delattr__
в своем классе. Например для очистки ресурсов (открытые файлы, сетевые соединения и т. д.), вы можете использовать __delattr__
для освобождения этих ресурсов при удалении атрибута; для логирования; для динамического изменения поведение объекта в зависимости от удаления атрибутов и др.
Магические методы для управления конструктором, деструктором и классом
__init__
: Конструктор объекта, вызывается при создании объекта.__del__
: Деструктор объекта, вызывается перед удалением объекта.__new__
: Магический метод, который создает новый объект в памяти до вызова__init__
.__call__
: Метод, позволяющий делать объекты вызываемыми, то есть вести себя как функции.
Магические методы для различных операций над объектами
__add__
,__sub__
,__mul__
,__truediv__
,__floordiv__
,__mod__
,__pow__
: Реализация арифметических операций: +, -, *, /, //, %, ^.__neg__
,__pos__
,__abs__
: Операции unary + и unary -, абсолютная величина.__eq__
,__ne__
,__lt__
,__le__
,__gt__
,__ge__
: Сравнения: ==, !=, <, <=, >, >=.__and__
,__or__
,__xor__
: Побитовые логические
Другие магические методы
__lshift__
,__rshift__
: Побитовые сдвиги: <<, >>.__invert__
: Побитовая инверсия (~).__radd__
,__rsub__
,__rmul__
,__rtruediv__
,__rfloordiv__
,__rmod__
,__rpow__
: Реализация арифметических операций для правых операндов (+, -, *, /, //, %, ^).__str__
,__repr__
: Превращает объект в строку для представления взаимодействия с пользователем и для отладки.__format__
: Форматирование строк с использованием спецификаций форматирования.__getattr__
,__getattribute__
,__setattr__
,__delattr__
: Позволяют реализовывать механизм получения, установки и удаления атрибутов динамически.__iter__
: Позволяет итерироваться по объекту с помощьюfor
или функций из модуляitertools
.__next__
: Возвращает следующий элемент после примененияnext()
к итератору.__call__
: Метод, позволяющий делать объекты вызываемыми, то есть вести себя как функции.__len__
: Реализация операцииlen()
.__contains__
: Метод, возвращающий True или False, если элемент содержится в коллекции. Часто используется для оператораin
.__hash__
: Когда объект используется в качестве ключа словаря, метод__hash__
определяет, как объект будет хешироваться.__copy__
,__deepcopy__
: Реализуют методы копирования объектов, используемые встроенными функциямиcopy.copy()
иcopy.deepcopy()
соответственно.__getitem__
: Метод, позволяющий получать элементы объектов коллекции по индексу.__setitem__
,__delitem__
: Методы, позволяющие менять элементы коллекции и удалять элементы по индексу соответственно.__missing__
: Вызывается, когда вставляемый элемент отсутствует в отображении (например, в словаре).__metaclass__
: Метакласс для объявления классов для класса (в Python 3:metaclass=
); используется для определения поведения создаваемых классов.
Перечисленный список не является полным перечнем всех магических методов в Python.