Классы и объекты
Что такое класс?
подробнее
Класс - это шаблон для создания объектов. Он определяет свойства (атрибуты) и поведение (методы), которые будут иметь объекты этого типа
Переменные в классе - его свойства (аттрибуты).
Функции в классе - его методы.
У любого класса есть конструктор - специальный метод, который вызывается при создании объекта.
Что такое экземпляр класса (объект)?
подробнее
Экземпляр класса (или объект) - это конкретная реализация класса, созданная на основе шаблона.
Жизненный цикл:
- Определение класса —
class MyClass: - Создание экземпляра —
obj = MyClass() - Использование — работа с атрибутами и методами
- Уничтожение — сборщик мусора удаляет объект, когда на него нет ссылок
Что такое Object и какие у него есть методы?
подробнее
Object — это базовый класс в Python, от которого наследуются все остальные классы. Это корень иерархии наследования в Python.
# Все классы неявно наследуются от object
class MyClass: # эквивалентно class MyClass(object):
pass
# Проверка
print(issubclass(MyClass, object)) # True
print(isinstance(MyClass(), object)) # True
Методы класса object:
- Базовые методы
__new__(cls, ...)- Создает и возвращает новый экземпляр класса__init__(self, ...)- Инициализирует новый экземпляр класса__del__(self)- Деструктор — вызывается при уничтожении объекта
- Методы представления
__str__(self)- Возвращает строковое представление объекта для пользователя__repr__(self)- Возвращает строковое представление объекта для разработчиков
- Методы сравнения
__eq__(self, other)- Определяет поведение оператора==__ne__(self, other)- Определяет поведение оператора!=__lt__(self, other),__le__(self, other),__gt__(self, other),__ge__(self, other)-<,<=,>,>=
- Методы арифметических операций
__add__(self, other),__sub__(self, other)-+,-__mul__(self, other),__truediv__(self, other)-*,/__floordiv__(self, other),__mod__(self, other),__pow__(self, other)-//,%,**
- Методы доступа к атрибутам
__getattr__(self, name)- Вызывается, когда атрибут не найден__setattr__(self, name, value)- Вызывается при установке любого атрибута__delattr__(self, name)- Вызывается при удалении атрибута
- Методы контейнеров
__len__(self)- Возвращает длину объекта__getitem__(self, key)- Позволяет доступ по индексу/ключу__setitem__(self, key, value)- Устанавливает значение по ключу__delitem__(self, key)- Удаляет элемент по ключу__contains__(self, item)- Определяет поведение оператораin
- Методы вызова
__call__(self[, args...])- Позволяет вызывать объект как функцию
- Методы контекстного менеджера
__enter__(self)- Вызывается при входе в блокwith__exit__(self, exc_type, exc_value, traceback)- Вызывается при выходе из блокаwith
- Полезные методы для интроспекции
__dir__(self)- Возвращает список атрибутов объекта__dict__- Словарь атрибутов экземпляра__class__- Возвращает класс объекта__module__- Возвращает имя модуля, в котором определен класс
Отличия атрибута класса от атрибута объекта, можно ли одинаковое имя сделать для них?
подробнее
- Атрибут класса
- Принадлежит классу, а не конкретному экземпляру
- Общий для всех экземпляров класса
- Определяется внутри класса, но вне методов
- Атрибут объекта (экземпляра)
- Принадлежит конкретному экземпляру класса
- Уникален для каждого объекта
- Определяется внутри методов, обычно в
__init__
Можно ли использовать одинаковые имена?
Да, можно, но это может привести к неожиданному поведению:
class Example:
x = 10 # Атрибут класса
def __init__(self):
self.x = 20 # Атрибут объекта с тем же именем
obj = Example()
print(obj.x) # 20 (атрибут объекта)
print(Example.x) # 10 (атрибут класса)
# Доступ к атрибуту класса через экземпляр
print(obj.__class__.x) # 10
# Как работает доступ к атрибутам:
class Test:
attr = "класс" # Атрибут класса
def __init__(self):
self.attr = "объект" # Атрибут объекта
obj = Test()
# Приоритет поиска атрибутов:
# 1. Атрибут объекта
# 2. Атрибут класса
# 3. Атрибуты родительских классов
# 4. AttributeError
print(obj.attr) # "объект" - найден в объекте первым
Атрибуты класса подходят для:
class DatabaseConnection:
# Константы
DEFAULT_TIMEOUT = 30
# Счетчики
connection_count = 0
# Общие настройки
config = {"host": "localhost", "port": 5432}
def __init__(self):
DatabaseConnection.connection_count += 1
self.connection_id = DatabaseConnection.connection_count
# Использование
print(DatabaseConnection.DEFAULT_TIMEOUT) # 30
conn1 = DatabaseConnection()
conn2 = DatabaseConnection()
print(DatabaseConnection.connection_count) # 2
Атрибуты объекта для:
class User:
def __init__(self, username, email):
# Уникальные данные каждого пользователя
self.username = username
self.email = email
self.login_count = 0
self.is_active = True
Проверка принадлежности атрибутов
class Test:
class_attr = "класс"
def __init__(self):
self.instance_attr = "объект"
obj = Test()
# Проверка наличия атрибута
print(hasattr(obj, 'class_attr')) # True
print(hasattr(obj, 'instance_attr')) # True
# Получение атрибутов
print(getattr(obj, 'class_attr', 'default')) # класс
# Проверка, где определен атрибут
print('class_attr' in obj.__dict__) # False (в классе)
print('instance_attr' in obj.__dict__) # True (в объекте)
print('class_attr' in Test.__dict__) # True (в классе)
Лучшие практики
- Избегайте одинаковых имен для атрибутов класса и объекта
- Используйте атрибуты класса для общих данных и констант
- Используйте атрибуты объекта для уникальных данных экземпляров
- Будьте осторожны с изменяемыми атрибутами класса
- Явно указывайте имя класса при работе с атрибутами класса
Как в классах хранятся атрибуты и методы? (__dict__)
подробнее
Аттрибуты в классах и объектах хранятся в словаре
__dict__в форматеимя: значение
Методы хранятся в__dict__класса, а не объекта