1

I have code below that is supposed to compare two dictionaries and if they are equal do nothing. If they are not equal and there are duplicate keys, throw an error. If the keys in dict2 are not duplicates, add the key and value to dict1.

    print 'dictionary 1 is', dict1
    print 'dictionary 2 is', dict2
    if dict1 == dict2:
        pass #does nothing since the two dictionaries are the same
    else:                   

       for key, val in dict2.items():
           if dict1.__contains__(key):
               print 'the value at', key, 'is', val.write() #prints the information stored in val which is dict2[key]
              print 'the other value at', key, 'is', dict1[key].write() #prints the information stored in dict1[key]
              raise KeyError('the added keys must be unique. Key {0} is a duplicate.'\.format(key))
           else:
              dict1[key] = val

The issue I am having is the dictionary comparison using == is showing as false, even though the objects stored in the dictionary have the same values inside the objects. The only difference is the pointer values for the objects in the dictionary. Does the == method not recursively check the equality of objects stored in the dictionary? Additionally, can someone give an explanation of the equality checking behavior in dictionaries for python?

The readout for the code skipping the traceback is:

dictionary 1 is {1: <coeffs_angle.Coeffs_angle object at 0x118c7f710>, 2: <coeffs_angle.Coeffs_angle object at 0x118c7f790>, 3: <coeffs_angle.Coeffs_angle object at 0x118c7f810>, 4: <coeffs_angle.Coeffs_angle object at 0x118c7f890>, 5: <coeffs_angle.Coeffs_angle object at 0x118c7f910>, 6: <coeffs_angle.Coeffs_angle object at 0x118c7f990>}
dictionary 2 is {1: <coeffs_angle.Coeffs_angle object at 0x118e17dd0>, 2: <coeffs_angle.Coeffs_angle object at 0x118e17e50>, 3: <coeffs_angle.Coeffs_angle object at 0x118e17ed0>, 4: <coeffs_angle.Coeffs_angle object at 0x118e17f50>, 5: <coeffs_angle.Coeffs_angle object at 0x118e17fd0>, 6: <coeffs_angle.Coeffs_angle object at 0x118e24090>}
the value at 1 is 89.5 113.3
the other value at 1 is 89.5 113.3

the code throws an error after the readout above. To confirm that the information stored in the objects in the dictionary is identical, I will list the rest of the readout assuming no error was thrown.

the value at 2 is 87.9 109.47
the other value at 2 is 87.9 109.47
the value at 3 is 74.5 111.4
the other value at 3 is 74.5 111.4
the value at 4 is 63.3 125.6
the other value at 4 is 63.3 125.6
the value at 5 is 126.5 123
the other value at 5 is 126.5 123
the value at 6 is 84.8 116.4
the other value at 6 is 84.8 116.4
Zachary Kraus
  • 1,051
  • 10
  • 21
  • Objects with same value are not equal unless you define their `__eq__` method. – Ashwini Chaudhary Feb 21 '15 at 02:33
  • Please don't do `if dict1.__contains__(key):`. It is unnecessarily complex. Just use `in`: `if key in dict1:`. –  Feb 21 '15 at 02:33
  • 1
    [Mappings (dictionaries) compare equal if and only if their sorted (key, value) lists compare equal. Outcomes other than equality are resolved consistently, but are not otherwise defined.](https://docs.python.org/2/reference/expressions.html#comparisons) – Ashwini Chaudhary Feb 21 '15 at 02:35
  • Thanks, I just changed dict1.__contains__(key): to if key in dict1: – Zachary Kraus Feb 21 '15 at 03:04

1 Answers1

3

Equality comparison on a mapping is performed recursively. However, the keys and values themselves must also support equality comparison in order to not be compared naively. This is done with the __eq__() method, which coeffs_angle.Coeffs_angle does not seem to implement.

Ashwini Chaudhary
  • 244,495
  • 58
  • 464
  • 504
Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
  • So would it be easier for me to write a work around or an __eq__ method for coeffs_angle.Coeffs_angle? I have never written an __eq__ method. – Zachary Kraus Feb 21 '15 at 02:54
  • The workaround would only work in that specific case. Implementing `__eq__()` will make the class work in any situation. – Ignacio Vazquez-Abrams Feb 21 '15 at 02:56
  • 1
    See https://docs.python.org/2.7/reference/datamodel.html#object.__eq__ for instructions on how to write `__eq__` correctly. In particular, if you ever might compare to other types of objects, see the bit about returning `NotImplemented`. – dcrosta Feb 21 '15 at 03:12
  • Thanks a ton. I ended up resolving the issue. I also found a great post on stack overflow that explains the way __eq__() method works recursively. http://stackoverflow.com/questions/3588776/how-is-eq-handled-in-python-and-in-what-order. – Zachary Kraus Feb 21 '15 at 03:25