Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to check if two object contain the same values in each of their variables in python?

How do I check if two instances of a

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

are identical? By identical I mean they have the same values in all of their variables.

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

I thought of

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

Will this do it without side effects?

The background for my question is unit testing. I want to achieve something like:

self.failUnlessEqual(self.my_object.a_function(), another_object)
like image 806
Aufwind Avatar asked Jun 21 '11 10:06

Aufwind


People also ask

How do you compare values in two objects in Python?

The == operator compares the value or equality of two objects, whereas the Python is operator checks whether two variables point to the same object in memory. In the vast majority of cases, this means you should use the equality operators == and != , except when you're comparing to None .

How do you check if something equals something in Python?

Use the equality ('==') operator to check if strings are equal or not. It will work case-sensitive manner i.e. uppercase letters and lowercase letters would be treated differently.

How do you check if 3 values are the same in Python?

a() == b() == c() is functionally equivalent to a() == b() and b() == c() whenever consecutive calls to b return the same value and have the same aggregate side effects as a single call to b . For instance, there is no difference between the two expressions whenever b is a pure function with no side-effects.


3 Answers

If you want the == to work, then implement the __eq__ method in your class to perform the rich comparison.

If all you want to do is compare the equality of all attributes, you can do that succinctly by comparison of __dict__ in each object:

class MyClass:      def __eq__(self, other) :          return self.__dict__ == other.__dict__ 
like image 138
AJ. Avatar answered Sep 20 '22 15:09

AJ.


For an arbitrary object, the == operator will only return true if the two objects are the same object (i.e. if they refer to the same address in memory).

To get more 'bespoke' behaviour, you'll want to override the rich comparison operators, in this case specifically __eq__. Try adding this to your class:

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 

(the comparison of all params could be neatened up here, but I've left them in for clarity).

Note that if the parameters are themselves objects you've defined, those objects will have to define __eq__ in a similar way for this to work.

Another point to note is that if you try to compare a FooBar object with another type of object in the way I've done above, python will try to access the param, param_2 and param_3 attributes of the other type of object which will throw an AttributeError. You'll probably want to check the object you're comparing with is an instance of FooBar with isinstance(other, FooBar) first. This is not done by default as there may be situations where you would like to return True for comparison between different types.

See AJ's answer for a tidier way to simply compare all parameters that also shouldn't throw an attribute error.

For more information on the rich comparison see the python docs.

like image 25
actionshrimp Avatar answered Sep 22 '22 15:09

actionshrimp


For python 3.7 onwards you can also use dataclass to check exactly what you want very easily. For example:

from dataclasses import dataclass

@dataclass
class FooBar:
    param: str
    param2: float
    param3: int

a = Foobar("test_text",2.0,3)
b = Foobar("test_text",2.0,3)

print(a==b)

would return True

like image 25
KZiovas Avatar answered Sep 21 '22 15:09

KZiovas