Error : list.remove(x) : x not in list, I don't understand why

Viewed 63

I'm working on a little text-based game and having a problem with removing element from a list. Here is a code to run that throws the error ValueError: list.remove(x): x not in the list but I don't see why.

LVL = 'lvl'
DAMAGE = 'damage'

Items = {
    'Sword':{
        LVL : 1,
        DAMAGE : 5,
    },

    'Wand':{
        LVL : 1,
        DAMAGE : 3,
    },
}

class player():
    def __init__(self):
        self.inventory = []

class item():
    def __init__(self, name: str, **kwarg):
        self.name = name
        self.dmg = kwarg.get(DAMAGE)
        self.lvl = kwarg.get(LVL)

    def __str__(self):
        return self.name

if __name__ == "__main__":
    user = player()
    for i in Items.keys():
        it = item(i, **Items[i])
        user.inventory.append(it)

    # check user's inventory
    print('Inventory after append items :')
    for i in user.inventory:
        print(i)

    # let's say i want the user to drop items
    items_name = [i for i in Items.keys()]
    items_to_drop = [item(i, **Items[i]) for i in items_name]
    for i in items_to_drop:
        user.inventory.remove(i)

My guess is that even if the items from user.inventory are the same as those in items_to_drop, the program sees it as two different variables. In which case I do not see how to perform what I want, that is removing items from user.inventory given a list filled with items to remove (because I cannot loop over user.inventory directly right ?)

I apologize if this question has been answered before. I have searched for it but with no success.

2 Answers

In the end, as suggested in comment, I had to overwrite __eq__() method of class item so that Python sees if two same items are actually in both user.inventory and items_to_drop. It works !

If needed, I simply did

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

One easy solution:

    # let's say i want the user to drop items
    items_name = [i for i in Items.keys()]
    items_to_drop = [item(i, **Items[i]) for i in items_name]
    for i in items_to_drop:
        try:
            user.inventory.remove(i)
        except:
            continue

another one and better one:

    # let's say i want the user to drop items
    items_name = [i for i in Items.keys()]
    items_to_drop = [item(i, **Items[i]) for i in items_name]
    invetory_copy = inventory.copy()
    for i in inventory:
        if i in items_to_drop:
            inventory_copy.remove(i)
    inventory = inventory_copy
Related