removing an instance of an object in python list

前端 未结 3 729
北恋
北恋 2020-12-11 01:13

I Think this should work but its giving me an error. I have a list that contains objects of class node. I have two different lists

  1. open_list
相关标签:
3条回答
  • 2020-12-11 01:53

    If I read the question right, python's default of comparing the memory locations is the behavior he is looking for, but is not getting. Here's a working example where a custom class is defined Node, it show's that there is no need for the __eq__(self, other).

    class Node(object):
        pass
    
    open_node_list = []
    node_list = []
    
    for i in range(10):
        a_node = Node()
        open_node_list.append(a_node)
        node_list.append(a_node)
    
    removed = open_node_list.pop()
    node_list.remove(removed)
    

    I can't be sure, because you did not show where your open_node_list and node_list were defined, but I suspect that the lists themselves reference the same list object. If that's the case, the popping from open_node_list also pops from node_list, therefore the node will no longer exist when you call remove. Here is example in which node_list and open_node_list are really the same list and so changes to one affect the other:

    class Node(object):
      pass
    
    open_node_list = []
    node_list = open_node_list # <-- This is a reference, not a copy.
    
    open_node_list.append(Node())
    print(node_list)
    

    One way you can copy a list is:

    node_list = open_node_list[:]
    
    0 讨论(0)
  • 2020-12-11 01:58

    In response to your followup, yes in will check for membership in a list, so:

    if removed in node_list: node_list.remove(removed)
    

    will not give you the error. Alternatively, you could trap the error:

    try:
        node_list.remove(removed)
    except ValueError:
        pass
    
    0 讨论(0)
  • 2020-12-11 01:59

    This is happening because what you understand as identifying features of two instances of your Node class, is not how python understands it.

    The problem lies here. Suppose you asked python 5==5, python would return True. This is because python knows about ints. However, Node is a custom class that you defined, so you need to tell python when two Node objects are the same. Since you (probably) haven't, python defaults to comparing their locations in memory. Since two separate instances will be in two different memory locations, python will return False. If you are familiar with Java at all, this is like the difference between == and .equals(...)

    In order to do this, go into your Node class and define the __eq__(self, other) method, where other is expected to be another instance of Node.

    For example, if your nodes have an attribute called name and two nodes that have the same name are considered to be the same, then your __eq__ could look like this:

    def __eq__(self, other):
        myName = self.name
        hisName = other.name
        if myName == hisName:
            return True
        else:
            return False
    

    Of course, the more elegant way of writing that same function is:

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

    When this is done, your error should disappear

    EDIT 1: In response to DSM's comment

    class Node: pass
    a = [Node(), Node()]
    b = a[:]
    b.remove(a.pop(0))
    

    This will work. But upon closer inspection, it becomes evident that a[0] and b[0] are in fact the same object. This can be verified by calling id(a[0]) and comparing it with id(b[[0]) to confirm that they are indeed the same

    EDIT 2: In response to the OP's follow up question (added to the original question as edit)

    Yes, the object not existing in the list will cause an error which would normally stop program flow. This can be solved in either of the following two ways:

    if x in my_list:
        my_list.remove(x)
    

    OR

    try:
        my_list.remove(x)
    except:
        pass
    

    The second method attempts to remove x from my_list and if that results in an error, ignores the error

    0 讨论(0)
提交回复
热议问题