Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python3中,如何在集合中循环,同时从集合中删除项_Python_Python 3.x_Iteration - Fatal编程技术网

在Python3中,如何在集合中循环,同时从集合中删除项

在Python3中,如何在集合中循环,同时从集合中删除项,python,python-3.x,iteration,Python,Python 3.x,Iteration,以下是我的情况: 我有一个列表/集合(不管是哪一个)的movieplayer对象,我想调用的“预加载”函数。这个预加载函数可以立即返回,但希望在将来返回一点 我想存储这个电影播放器集合,表明它们还没有被预加载,然后在它们之间循环,调用preload函数。preload函数返回时,会将它们从集合中删除(这样我就知道它们何时都已预加载) 然而,我认为,因为python正在等待预加载函数,然后删除播放器,所以在迭代错误期间,我得到了一个集大小的更改 嘿,这是我的代码的简化版本,我希望能找到一种解决这个

以下是我的情况:

我有一个
列表/集合
(不管是哪一个)的
movieplayer
对象,我想调用
的“预加载”
函数。这个预加载函数可以立即返回,但希望在将来返回一点

我想存储这个电影播放器集合,表明它们还没有被预加载,然后在它们之间循环,调用
preload
函数。
preload
函数返回时,会将它们从集合中删除(这样我就知道它们何时都已预加载)

然而,我认为,因为python正在等待
预加载
函数,然后删除播放器,所以在迭代错误期间,我得到了一个
集大小的更改

嘿,这是我的代码的简化版本,我希望能找到一种解决这个问题的方法

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.

我能想到的唯一解决方案是将
集合a
复制成
副本,然后进行迭代,但我不确定这样做是否正确,或者是否可行。

没有必要重复列表2次!正如你所说,它将引发
大小更改
错误。因此,您可以使用
set
list
pop
属性来获取返回值的项目,并将其从数据结构中删除。对于列表,您可以在每次迭代中将0索引传递给
pop
,这也是您可以使用的一种更为pythoinc的方法当您要从数据结构中删除项时,请使用
而不是
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
中每个
播放器的成员资格。最后,
preload()
应该执行预加载播放器所需的任何操作,但它不应该负责维护外部数据结构(
a

更好的设计是让
preload()
返回一个布尔值,指示预加载是否成功。然后可以在预加载功能之外移除成功加载的播放器:

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"
此代码仅在玩家成功预加载后删除该玩家

但我希望将来能回来一点

如果要异步调用preload函数,我将使用以下模块:


你的预加载功能有两个职责,这是一个太多的发布代码,实际上显示了问题-我相信它应该是
中的玩家:preload(player)
@PeterWood我想我喜欢你的做法,但你能详细说明一下吗?@mhawke你是对的,我编辑了我的代码,我无法复制精确的代码,因为它依赖于嵌入在外部程序中的电影播放器和python播放器。这看起来很棒。新列表中玩家的
id
s是否与a中对应的玩家相同?也就是说,
的计算结果是否为真?@Startec是的,它们是相同的对象。
.pop()
是正确的选择,正如@Kasra所说,它将用于
列表
设置
(以及更多)而且在copy.fwiw中不会浪费任何东西:当从列表中弹出时,也可以忽略
0
,然后从列表的末尾弹出。顺序似乎并不重要…@Kasra,这个方法不是会立即从列表或集合中删除该项吗?我只想在预加载功能完成时删除它们(因为可能有错误,我需要知道哪个玩家没有预加载)@Startec是的,没错!但在这种情况下,因为订单很重要,我们不能这样做@Startec,因此,您可以检查列表或集合中是否存在项目!如果它在
集合中
则表示该项目未预加载!
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()