Подтвердить что ты не робот

Есть ли способ проверить, содержат ли два объекта одинаковые значения в каждой из своих переменных в python?

Как проверить, если два экземпляра

class FooBar(object):
    __init__(self, param):
        self.param = param
        self.param_2 = self.function_2(param)
        self.param_3 = self.function_3()

идентичны? По идентичности я имею в виду, что они имеют одинаковые значения во всех своих переменных.

a = FooBar(param)
b = FooBar(param)

Я думал о

if a == b:
    print "a and b are identical"!

Будет ли это делать без побочных эффектов?

Фон для моего вопроса - это модульное тестирование. Я хочу добиться чего-то вроде:

self.failUnlessEqual(self.my_object.a_function(), another_object)
4b9b3361

Ответ 1

Если вы хотите, чтобы == работал, затем реализуйте метод __eq__ в своем классе для выполнения богатого сравнения.

Если все, что вы хотите сделать, это сравнить равенство атрибутов all, вы можете сделать это в сжатом виде путем сравнения __dict__ в каждом объекте:

class MyClass:

    def __eq__(self, other) : 
        return self.__dict__ == other.__dict__

Ответ 2

Для произвольного объекта оператор == возвращает только true, если оба объекта являются одним и тем же объектом (т.е. если они относятся к одному и тому же адресу в памяти).

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

def __eq__(self, other):
    if self.param == other.param \
    and self.param_2 == other.param_2 \
    and self.param_3 == other.param_3:
        return True
    else:
        return False

(сравнение всех параметров можно было бы здесь аккуратно, но я оставил их для ясности).

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

Еще одно замечание: если вы попытаетесь сравнить объект FooBar с другим типом объекта так, как я это сделал выше, python попытается получить доступ к параметрам param, param_2 и param_3 другого типа объекта, будет вызывать AttributeError. Вероятно, вы захотите проверить объект, с которым вы сравниваете, - это экземпляр FooBar с isinstance (другой, FooBar). Это не выполняется по умолчанию, так как могут быть ситуации, когда вы хотели бы вернуть True для сравнения между различными типами.

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

Для получения дополнительной информации о богатом сравнении см. документы python.

Ответ 3

Чтобы избежать возможности добавления или удаления атрибутов модели и забывания сделать соответствующие изменения в вашей функции __eq__, вы можете определить ее следующим образом.

def __eq__(self, other):
    if self.__class__ == other.__class__:
        fields = [field.name for field in self._meta.fields]
        for field in fields:
            if not getattr(self, field) == getattr(other, field):
                return False
        return True
    else:
        raise TypeError('Comparing object is not of the same type.')

Таким образом сравниваются все атрибуты объекта. Теперь вы можете проверить равенство атрибута либо с помощью object.__eq__(other), либо object == other.