如何循环遍历集合,同时从 Python 中的集合中删除项目 3
How to loop through a set, while removing items from the set in Python 3
这是我的情况:
我有一个 list/set
(哪个无关紧要)movieplayer
个对象,我想对其调用 "preload"
函数。此预加载功能可以 return 立即但希望 return 稍后。
我要存储这个movieplayer集合,说明还没有预加载,然后循环遍历,调用preload
函数。 preload
函数在 returned 时会将它们从集合中删除(因此我会知道它们何时全部预加载)。
但是,我认为因为 python 正在等待 preload
函数,然后删除播放器,我得到 set size changed during iteration error
。
嘿,这是我的代码的简化版本,我希望能找到解决此问题的方法。
a = set([mp1, mp2 mp3])
for player in a:
preload(player)
# preload would be something like
def preload(player):
player.preloadVideo()
a.remove(player)
# This is where I believe the error gets generated.
我能想到的唯一解决方案是对 set a
创建一个 copy
,然后遍历它,但我不确定这是否是正确的方法它甚至会起作用。
无需遍历列表 2 次!正如您所说,它会引发 size changed
error.So 而不是您可以使用 set
和 list
的 pop
属性 来获取那些 return 值并将其从数据中删除 structure.For 一个列表,您可以在每次迭代中将 0 索引传递给 pop
也可以作为一种更 pythoinc 的方式,您可以使用 while
而不是for
当您想从数据结构中删除项目时:
a = [mp1, mp2 mp3]
while a:
preload(a.pop(0))
但是对于 set
,pop 不接受索引:
a = set([mp1, mp2 mp3])
while a:
preload(a.pop())
示例:
>>> def preload(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([])
您可以通过迭代集合的副本来修复它。我在这里使用了list()
:
a = set(['mp1', 'mp2', 'mp3'])
# preload would be something like
def preload(player):
player.preloadVideo()
a.remove(player)
for player in list(a):
preload(player) # N.B. pass player, not a
然而,这并不是一个很好的设计。一方面,全局变量 a
是从 preload()
函数中引用的。此外,for 循环遍历集合中的所有元素,依次将每个元素传递给 preload()
,因此没有必要检查 a
中每个 player
的成员资格。最后,preload()
应执行预加载播放器所需的任何操作,但不应负责维护外部数据结构 (a
)。
更好的设计是 preload()
到 return 一个布尔值,指示预加载是否成功。然后可以在预加载函数之外删除成功加载的播放器:
a = set(['mp1', 'mp2', 'mp3'])
# preload would be something like
def preload(player):
return player.preloadVideo() # assume that this returns boolean
for player in list(a):
if preload(player):
a.remove(player)
if len(a):
print "{} player(s) failed to preload: {}".format(len(a), a)
else:
print "All players successfully preloaded"
此代码只会在成功预加载后删除播放器。
but would like return a bit in the future.
如果你想异步调用预加载函数,我会使用multiprocessing模块:
from multiprocessing import Pool
a = set([mp1, mp2, mp3])
def preload(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 is not None}
p.close()
这是我的情况:
我有一个 list/set
(哪个无关紧要)movieplayer
个对象,我想对其调用 "preload"
函数。此预加载功能可以 return 立即但希望 return 稍后。
我要存储这个movieplayer集合,说明还没有预加载,然后循环遍历,调用preload
函数。 preload
函数在 returned 时会将它们从集合中删除(因此我会知道它们何时全部预加载)。
但是,我认为因为 python 正在等待 preload
函数,然后删除播放器,我得到 set size changed during iteration error
。
嘿,这是我的代码的简化版本,我希望能找到解决此问题的方法。
a = set([mp1, mp2 mp3])
for player in a:
preload(player)
# preload would be something like
def preload(player):
player.preloadVideo()
a.remove(player)
# This is where I believe the error gets generated.
我能想到的唯一解决方案是对 set a
创建一个 copy
,然后遍历它,但我不确定这是否是正确的方法它甚至会起作用。
无需遍历列表 2 次!正如您所说,它会引发 size changed
error.So 而不是您可以使用 set
和 list
的 pop
属性 来获取那些 return 值并将其从数据中删除 structure.For 一个列表,您可以在每次迭代中将 0 索引传递给 pop
也可以作为一种更 pythoinc 的方式,您可以使用 while
而不是for
当您想从数据结构中删除项目时:
a = [mp1, mp2 mp3]
while a:
preload(a.pop(0))
但是对于 set
,pop 不接受索引:
a = set([mp1, mp2 mp3])
while a:
preload(a.pop())
示例:
>>> def preload(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([])
您可以通过迭代集合的副本来修复它。我在这里使用了list()
:
a = set(['mp1', 'mp2', 'mp3'])
# preload would be something like
def preload(player):
player.preloadVideo()
a.remove(player)
for player in list(a):
preload(player) # N.B. pass player, not a
然而,这并不是一个很好的设计。一方面,全局变量 a
是从 preload()
函数中引用的。此外,for 循环遍历集合中的所有元素,依次将每个元素传递给 preload()
,因此没有必要检查 a
中每个 player
的成员资格。最后,preload()
应执行预加载播放器所需的任何操作,但不应负责维护外部数据结构 (a
)。
更好的设计是 preload()
到 return 一个布尔值,指示预加载是否成功。然后可以在预加载函数之外删除成功加载的播放器:
a = set(['mp1', 'mp2', 'mp3'])
# preload would be something like
def preload(player):
return player.preloadVideo() # assume that this returns boolean
for player in list(a):
if preload(player):
a.remove(player)
if len(a):
print "{} player(s) failed to preload: {}".format(len(a), a)
else:
print "All players successfully preloaded"
此代码只会在成功预加载后删除播放器。
but would like return a bit in the future.
如果你想异步调用预加载函数,我会使用multiprocessing模块:
from multiprocessing import Pool
a = set([mp1, mp2, mp3])
def preload(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 is not None}
p.close()