Unable to remove objects from a list in another object
<p>Here is some test code to describe my problem.  I have created two classes as follows...</p>

<pre><code>class Card:
    def __init__(self, suit, rank):
        self.suit = suit
        self.rank = rank

class Deck:
    def __init__(self):
        self.cards = []
        for suit in range(4):
            for rank in range(13):
                card = Card(suit, rank)
                self.cards.append(card)

d = Deck()
d.cards.remove(Card(1, 1))
</code></pre>

<p>After the last remove command, I get the following error:</p>

<pre><code>Traceback (most recent call last):
  File "&lt;pyshell#111&gt;", line 1, in &lt;module&gt;
    d.cards.remove(Card(1, 1))
ValueError: list.remove(x): x not in list
</code></pre>

<p>Does anyone know why this is occurring?  I can confirm the d object gets initialized with 52 total Card objects from (0, 0) to (3, 13).  Why does it not detect this with the remove module?  Furthermore, I can do the following commands after the initialization and it works with no problem.</p>

<pre><code>d.cards.append(Card(1, 1))
d.cards.remove(Card(1, 1))
</code></pre>

<p>This adds and then remove the Card that was just added to the list, but it will not remove the card that was initialized with the same value.</p>

<p>You didn't define when two <code>Card</code> instances are equal. Without such a definition, <code>list.remove()</code> can't find anything that is equal (<code>obj1 == obj2</code> is true). The default implementation for custom classes is to be equal only when the object is <em>identical</em> (the exact same object, <code>reference1 is reference2</code> is true).</p>

<p>Add an <a href="https://docs.python.org/3/reference/datamodel.html#object.__eq__" rel="nofollow"><code>__eq__</code> method</a> to your class to define what equality means for <code>Card</code> instances.</p>

<p>For example, if two <code>Card</code> instances are equal if and when both <code>rank</code> and <code>suit</code> are equal, then implement that test:</p>

<pre><code>def __eq__(self, other):
    if not isinstance(other, Card):
        return NotImplemented
    return self.rank == other.rank and self.suit == other.suit
</code></pre>

<p>Now <code>list.remove()</code> can find the first object that tests equal to the one you passed in to that method.</p>

<p>Note that:</p>

<pre><code>d.cards.append(Card(1, 1))
d.cards.remove(Card(1, 1))
</code></pre>

<p><em>can't work</em> without <code>__eq__</code> defined. That code creates two separate instances, and without a custom <code>__eq__</code> method two separate instances never test as equal.</p>

<p>You most likely did this instead:</p>

<pre><code>card = Card(1, 1)
d.cards.append(card)
d.cards.remove(card)
</code></pre>

<p>because only then would the object test as equal; it is, after all, <em>the same object</em>.</p>

python