Skip to content Skip to sidebar Skip to footer

How To Loop Through A Set, While Removing Items From The Set In Python 3

Here is my situation: I have a list/set (doesn't matter which) of movieplayer objects that I want to call a 'preload' function on. This preload function could return immediately b

Solution 1:

You can fix it by iterating over a copy of the set. I've used list() here:

a = set(['mp1', 'mp2', 'mp3'])

# preload would be something likedefpreload(player):
    player.preloadVideo()
    a.remove(player)

for player inlist(a):
    preload(player)    # N.B. pass player, not a

This, however, is not a great design. For one thing the global variable, a is referenced from within the preload() function. Furthermore, the for loop iterates over all elements of the set passing each in turn to preload(), so it is not necessary to check membership of each player in a. Lastly, preload() should perform whatever is required to preload the player, but it should not be responsible for maintaining an external data structure (a).

A better design is for preload() to return a boolean indicating whether the preload was successful or not. Removal of a successfully loaded player can then be done outside of the preload function:

a = set(['mp1', 'mp2', 'mp3'])

# preload would be something likedefpreload(player):
    return player.preloadVideo()    # assume that this returns booleanfor player inlist(a):
    if preload(player):
        a.remove(player)

iflen(a):
    print"{} player(s) failed to preload: {}".format(len(a), a)        
else:
    print"All players successfully preloaded"

This code will only remove a player once it has been successfully preloaded.

Solution 2:

There is no need to loop over your list 2 time! as you said, it will raise a size changed error.So instead you can use pop property of set and list to get those items which return the value and remove it from your data structure.For a list you can pass the 0 index to pop in each iteration also as a more pythoinc way you can use while instead of for when you want to remove item from your data structure :

a = [mp1, mp2 mp3]
while a:
    preload(a.pop(0))

But for set the pop doesn't accept the index:

a = set([mp1, mp2 mp3])
while a:
    preload(a.pop())

Example :

>>>defpreload(i):...print i...>>>a=[1,2,3]>>>while a:...    preload(a.pop(0))... 
1
2
3
>>>a
[]
>>>a={1,2,3}>>>while a:...    preload(a.pop())... 
1
2
3
>>>a
set([])

Solution 3:

but would like return a bit in the future.

If you want to call the preload function asynchronously, I’d use the multiprocessing module:

from multiprocessing import Pool

a = set([mp1, mp2, mp3])

defpreload(player):
    try: # Change it to if/else depending on your type of error handling
        player.preload()
    except:
        return player

p = Pool(5) # uses 5 threads to do the computation, change it accordingly
uninitialized = {players for players in p.map(preload, a) if player isnotNone}
p.close()

Post a Comment for "How To Loop Through A Set, While Removing Items From The Set In Python 3"