Ecto Ruseff
Ecto Ruseff

Reputation: 191

Python lists not equal when they should

Can somebody please explain why both of lists are not equal? I mean output should be True but it's output is False. Why?

    # CASE 1
    list1 = []
    for item in [self.home_btn, self.secret_dir_btn, self.info_btn]:
        list1.append(QPropertyAnimation(item, b"size"))

    # CASE 2
    self.home_btn_anim = QPropertyAnimation(self.home_btn, b"size")
    self.secret_dir_btn_anim = QPropertyAnimation(self.secret_dir_btn, b"size")
    self.info_btn_anim = QPropertyAnimation(self.info_btn, b"size")
    list2 = [self.home_btn_anim, self.secret_dir_btn_anim, self.info_btn_anim]

    # Output
    print(list1 == list2)
    # Further code

Also, if I'm using case 1 to create the list, my further code doesn't work as it should. but using Case 2 to create the list makes the code work correctly. Why? and how can I solve it.

Upvotes: 0

Views: 723

Answers (2)

eyllanesc
eyllanesc

Reputation: 244202

As they have already pointed out to you, the comparison between sequences is given element by element, considering that what you are trying to do is compare the QPropertyAnimation.

On the other hand, for design reasons, QObjects are not comparable since they handle many internal states that imply that even though they have the same properties, they will not behave in the same way. And the QPropertyAnimation are QObject so they inherit that limitation as well.

Considering this, it is not recommended to implement the __eq__ method since it contradicts the predefined design, instead if you want to compare some properties then create a method that compares property by property:

def compare_animations(animation1, animation2):
    return (
        animation1.target() is animation2.target()
        and animation1.propertyName() == animation2.propertyName()
    )
equals = all([compare_animations(anim1, anim2) for anim1, anim2 in zip(list1, list2)])
print(equals)

Upvotes: 2

Chase
Chase

Reputation: 5615

First, a refresher on how python compares sequences.

Sequences of the same type also support comparisons. In particular, tuples and lists are compared lexicographically by comparing corresponding elements. This means that to compare equal, every element must compare equal and the two sequences must be of the same type and have the same length.

So every element must be equal to its corresponding element from the other sequence. How is equality for objects checked? If an object does not implement __eq__, comparison between 2 of objects of that type only checks if both objects are the exact same. As in, references to the same object - this is what the is operator does.

class Foo():
    pass

a = Foo()
b = Foo()

print(a is a)
# prints true
print(a is b)
# prints false

Since QPropertyAnimation does not implement __eq__, only the is check can be performed. Which obviously results in false for different object references.

If you want to, you can extend QPropertyAnimation and implement your own __eq__-

class MyQPropertyAnimation(QPropertyAnimation):
    def __eq__(self, other):
        if not isinstance(other, QPropertyAnimation):
            # Don't compare against other types
            return NotImplemented
        # Check if the properties `target` and `propertyName` are equal for both objects
        return self.target == other.target and self.propertyName == other.propertyName

But please note that, implementing equality for an animation object probably isn't ideal. But if you strictly want equality based on those properties for your usecase, then this may be fine.

Upvotes: 1

Related Questions