简体   繁体   中英

Why list.remove() doesn't work “properly”?

I have a class (Points) which has 4 lists and a list container. in my main I'm trying to pop a value from one of the lists. If the list becomes empty, then I remove it from the container. This all works fine, but sometimes the output says it tries to remove the same list from the container as before. Why is it working in this way?

My code:

class Points():

    def __init__(self):
        points = ["One", "Two", "Three", "Four", "Five"]
        self.A = points.copy()
        self.B = points.copy()
        self.C = points.copy()
        self.D = points.copy()
        self.container = [self.A, self.B, self.C, self.D]

    def getPoint(self, letter, index):
        try:
            res = self.container[letter].pop(index-1)

            if (len(self.A) == 0) and (self.A in self.container):
                print("OUT OF A")
                self.container.remove(self.A)
            if (len(self.B) == 0) and (self.B in self.container):
                print("OUT OF B")
                self.container.remove(self.B)
            if (len(self.C) == 0) and (self.C in self.container):
                print("OUT OF C")
                self.container.remove(self.C)
            if (len(self.D) == 0) and (self.D in self.container):
                print("OUT OF D")
                self.container.remove(self.D)
        except:
            return -1
        return res

if __name__ == "__main__":
    m_Points = Points()

    for item in range(25):
        try:
            letterCode = randint(0,len(m_Points.container)-1)
            letter = m_Points.container[letterCode]
            index = randint(0, len(letter) )
            print("#{}. {}".format(item, m_Points.getPoint(letterCode, index) ))
        except:
            print("No more points")
            break

The output:

#0. Four
#1. One
#2. Three
#3. One
#4. Five
#5. Three
#6. Five
#7. Four
#8. Four
#9. Two
OUT OF B
#10. Two
#11. Two
OUT OF A           <--- First time A
#12. One
#13. Five
#14. Four
#15. Three
OUT OF A           <--- A AGAIN?
#16. One
#17. Five
#18. Two
OUT OF A           <--- and again...
#19. Three
No more points

The reason is the way in and remove work.

Your confusion probably stems from a misconception that in asks if a particular container contains a specific object , and remove removes a specific object , and so when you call, say, .remove(self.A) , you want *the list pointed to by self.A to be removed.

However, what instead happens is that in just looks if an object with a particular value exists in the container, and remove removes the first object with that value in the container. In both cases, that need not be self.A , just an object with the same value .

Therefore, eventually, we will have something like this:

self.A = ['First']
self.container = [['First'], ['First'], ['First']]

# ...check and remove goes here

In this situation, what happens is that since self.container does contain a list with value equal to self.A and self.A is not empty, the first check passes and you reach print('OUT OF A') . Then, the first list is removed, but the condition is still true the next iteration , since all the remaining lists have the same value!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM