Python for循环给列表添加一个元素

6 投票
2 回答
3206 浏览
提问于 2025-04-17 07:31

我正在处理鼠标点击事件,主要是根据屏幕上物体的位置来判断。每当鼠标点击时,我会记录下点击的xy坐标,然后检查这个坐标是否和可以点击的物体匹配。这些物体可能在不同的列表里,或者只是单个物体,但我希望把它们放在一个大列表里,这样我就可以一次性遍历整个列表。如果点击的是某个物体,就执行相应的操作,然后停止。因为每次只能点击一个物体。

第一种方法:这是我现在的做法:

list = [obj1, obj2, obj3]
singleobj

copylist = list
copylist.append(singleobj)

for item in copylist:
    if item.pos == mouseclick.pos:
        doWork(item)
        break

第二种方法:我更想用下面这种方式,但显然 list+singleobj 这种写法是无效的:

for item in list+singleobj:
    if item.pos == mouseclick.pos:
        doWork(item)
        break

第三种方法:如果我真的必须这样做,我可以写出这种糟糕的代码:

list = [obj1, obj2, obj3]

foundobj = None

for item in list:
    if item.pos == mouseclick.pos:
        foundobj = item
        break

if foundobj is None:
    if singleobj.pos == mouseclick.pos:
        foundobj = singleobj

#possibly repeated several times here....


if foundobj is not None:
    doWork(foundobj)

第一种方法看起来比较慢,因为我需要把所有(可能很多的)列表和单个物体复制到一个列表里。

第二种方法看起来很理想,因为它简洁且易于维护。不过,现在的写法只是伪代码。

第三种方法则显得笨重且不灵活。

我应该用哪种方法?如果用第二种,能给我实际的代码吗?

2 个回答

5

DrTyrsa的回答正好是我想说的内容,不过我还有一些其他的小建议:

copylist = list
copylist.append(singleobj)

这段代码并没有创建列表的副本,你可能想用 copylist = list[:] 或者 copylist = list(lst) 来创建一个副本(我把这里的名字改成了 lst,因为 list 是一个内置的名称,你知道的)。

关于你的第二种方法,你可以这样做:

for item in list + [singleobj]:
    ...

如果你打算使用itertools,一个小改进是用元组来存放额外的对象,而不是列表,因为元组稍微轻量一些:

for item in itertools.chain(list, (singleobj,)):
    ...

还有一点就是,你不应该一个个遍历你的对象来检查坐标是否匹配,你可以通过它们的边界来索引(比如用BSP树或四叉树),这样查找会更快。

12

第二种方法需要用到 itertools.chain

for item in itertools.chain(list, [singleobj]):
    ...

撰写回答