Сравнение экземпляров объектов в Python по атрибутам

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Для сравнения объектов на равенство, исходя из их атрибутов, необходимо переопределить метод __eq__. Это хороший способ, особенно когда требуется сравнивать все атрибуты объекта:

Python
Скопировать код
class MyClass:
    def __init__(self, *args):
        self.attributes = args

    def __eq__(self, other):
        return isinstance(other, MyClass) and all(getattr(self, attr) == getattr(other, attr) for attr in vars(self))

obj1 = MyClass(1, 'a')
obj2 = MyClass(1, 'а')
print(obj1 == obj2)  # Вернёт "True", если объекты равны

Данный подход эффективен, масштабируем и легко поддерживается, особенно при наличии большого количества атрибутов у класса.

Кинга Идем в IT: пошаговый план для смены профессии

Подробнее о __eq__

Перед сравнением атрибутов убедитесь, что типы сравниваемых объектов совпадают:

Python
Скопировать код
if not isinstance(other, self.__class__):
    return NotImplemented

Если ваши объекты неизменяемые, то реализуйте __hash__ для возможности их использования в качестве ключей в словарях или элементов множеств:

Python
Скопировать код
def __hash__(self):
    return hash(tuple(sorted(self.__dict__.items())))

За пределами __eq__

Полное сравнение

Для полноценной реализации операций сравнения определите методы __lt__, __le__, __gt__ и __ge__.

Глубокое сравнение

При необходимости сравнения объектов с вложенными атрибутами можно воспользоваться функцией pickle.dumps:

Python
Скопировать код
import pickle

def __eq__(self, other):
    return isinstance(other, MyClass) and pickle.dumps(self) == pickle.dumps(other)

Dataclasses: новый подход к работе со структурами

С Python 3.7 стали доступными dataclasses, которые автоматизируют сравнение атрибутов и многие другие операции:

Python
Скопировать код
from dataclasses import dataclass

@dataclass
class MyClass:
    foo: int
    bar: str

Важность выбора версии Python

Особенности Python 2

В Python 2 для полноценного сравнения объектов необходимо также определить метод __ne__:

Python
Скопировать код
def __ne__(self, other):
    return not self.__eq__(other)

В Python 2 присутствует метод __cmp__, предназначенный для организации сравнения:

Python
Скопировать код
def __cmp__(self, other):
    if isinstance(other, MyClass):
        # тело метода

Визуализация

Сравнение объектов можно представить как подбор подходящих элементов пазла:

Markdown
Скопировать код
Объект A (🧩): {цвет: 'красный', форма: 'квадрат', размер: 'средний'}
Объект B (🧩): {цвет: 'красный', форма: 'квадрат', размер: 'средний'}

Совпадают ли все атрибуты?

Markdown
Скопировать код
🧩==🧩: [цвет ✅, форма ✅, размер ✅]
# Отлично! Объекты A и B равны.

Сравнение неупорядоченных коллекций

Если атрибуты представлены в виде неупорядоченных коллекций, используйте сортировку:

Python
Скопировать код
class MyClassWithList:
    def __init__(self, elements):
        self.elements = elements

    def __eq__(self, other):
        return isinstance(other, MyClassWithList) and sorted(self.elements) == sorted(other.elements)

Разнообразие при сравнении

Для сравнения объектов с одинаковыми атрибутами, но представленными различными типами данных, используйте приведение типов:

Python
Скопировать код
class MyClassWithString:
    def __init__(self, num_str):
        self.num_str = num_str

    def __eq__(self, other):
        return str(self) == str(other)

Полезные материалы

  1. 3. Data model — Python 3.12.2 documentation – описание метода __eq__ для сравнения объектов в Python.
  2. Python '!=' Is Not 'is not': Comparing Objects in Python – Real Python – обсуждение различия между is и == в Python.
  3. dataclasses — Data Classes — Python 3.12.2 documentation – документация о классах данных в Python 3.7 и новее.
  4. attrs 23.2.0 documentation – библиотека для упрощения сравнения объектов.
  5. Operator Overloading in Python – GeeksforGeeks – подробно о переопределении операторов в Python для сравнения созданных объектов.