emptying a list from pointers

hello again!
Today (tonight here) I am fighting with this problem. I can’t empty a list of objects.

For a simpler understanding

class Army; which contains the unitList which is the list of all unit/structures on scen. Contains function delete all units which i posted above. Unit is my personal class and it’s similar to this.

class Unit(DirectObject.DirectObject):
    def __init__(self, model, x=0, y=0, z=0):
        self.node = loader.loadModel("models/" + model + ".egg")
        self.node.setPos(x,y,z)
        self.node.reparentTo(render)
#function that i use to remove all my RTS's units from the main units list.
    def removeAll(self):
        #create a copy of my unitList (member of my class) in order to prevent main list to be broken - am I right?
        tmpList = self.unitList
        # than loop over all the tmpList (which is equal to unitList)
        for unit in tmpList:
            #remove the object (unit is type of my Unit class containing a member called node which is nodepath)
            unit.node.remove()
            #the i try to remove all the units because this actually doesn't work... it leave one object on the scene.
            #confirmed by render.ls() too
            self.unitList.remove(unit)
        #delete temporary list
        del tmpList
    #end of function

it’s well documented explaining my stupidity :laughing: i think it’s more a python problem than panda.

Anyway, thank you a lot in advance!

And if you have any suggestion I’d really appreciate since I’ve just written code for 2 weeks with panda and I’m still a big newbie here :smiley:

Hi,

tmpList = self.unitList

This is useless because self.initList is the actual list, when you say newVar = self.initList It’s just assigning a pointer to that list… You can look up pointers for more information on this subject.

Instead you can just loop over the real list, and as long as you never remove an item from that list (list.remove(item)) then you are never tampering with the list, just scanning the items in it.

unit.node.remove()

This should work fine, assuming that unit.node is a nodePath… are you sure it is? perhaps if this is just a model loaded via loader.loadModel or something similar, try:

self.unitList.remove(unit)

I’m unable to understand why you would want to remove the item from the original list, perhaps I’ve misunderstood due to lack of knowledge on your code (perhaps this is a list of classes holding units?)

In any case, the following should work:

    def removeAll(self):
        for unit in self.initList:
            unit.node.remove()

            #self.unitList.remove(unit) # Why?
        #del tmpList #No need for this anymore

[/b]

If you want to loop over a list while removing items here are a few ways to do it.

Make a copy of the list:

for item in list[:]:
    do_something(item)
    list.remove(item)

Go in reverse order:

for i in reversed(range(0, len(list))):
    item = list[i]
    do_something(item)
    list.remove(item)

Use while loop instead of for:

while list:
    item = list.pop(0)
    do_something(item)

As for why you have one item left over, it could be because of the loop, or maybe your class has some code outside of a function that is executing when the class is defined. Do you mean one item left in your list or one 3d model not removed from the scene?

Thanks to both of you!
Now it works:

def removeAll(self):
        for unit in self.unitList[:]:
            unit.node.remove()
            self.unitList.remove(unit)

yes maybe in my first function I should have written my tmpList like that:

tmpList = self.unitList[:]

now is fine! Thanks! :smiley:

edit: and the object that was still in the scene was both in pointer list and as a model child of render… but no more problem :slight_smile: