繁体   English   中英

使用for循环附加要迭代的列表

[英]appending a list that you are iterating over with a for loop

有人提到下面的函数(在这种情况下为方法)不好,因为它在迭代列表时会修改列表。 为什么这样做,因为它完全符合我的预期。 实际上,我对此感到非常满意……是否有更好的书写方式。

数据结构,功能和输出如下:

nodes = { ('foo','bar',1),
          ('foo','baz',1),
          ('baz','gad',0),
          ('boo','moo',1),
          ('goo','loo',0),
          ('bar','far',1),
          ('far','aaa',0) }

class Graph(dict):

    def __missing__(self, key):
        self[key] = set()
        return self[key]

    def add_node_pairs(self, node_pairs):
        for pair in node_pairs:
            nodeA, nodeB, weight = pair
            self[nodeA].add((weight, nodeB))
            self[nodeB].add((weight, nodeA)) 

    def find_paths(self, keys):      
        paths = [(key,) for key in keys if key in self]
        for path in paths:
            *oldkeys, key = path
            for weight, next_key in self[key]:
                if next_key not in oldkeys:
                    paths.append( path + (weight,next_key) )

        paths.sort()
        return paths

graph = Graph()
graph.add_node_pairs(nodes)
print(graph)
print( graph.find_paths(['foo']))

图形:

{ 'goo': {(0, 'loo')}, 
  'foo': {(1, 'bar'), (1, 'baz')}, 
  'aaa': {(0, 'far')}, 
  'far': {(1, 'bar'), (0, 'aaa')}, 
  'baz': {(0, 'gad'), (1, 'foo')}, 
  'loo': {(0, 'goo')}, 
  'moo': {(1, 'boo')}, 
  'boo': {(1, 'moo')}, 
  'bar': {(1, 'far'), (1, 'foo')}, 
  'gad': {(0, 'baz')} }

find_paths('foo'):

[ ('foo',), 
  ('foo', 1, 'bar'), 
  ('foo', 1, 'bar', 1, 'far'), 
  ('foo', 1, 'bar', 1, 'far', 0, 'aaa'), 
  ('foo', 1, 'baz'), 
  ('foo', 1, 'baz', 0, 'gad') ]

考虑以下三个示例:

l = [1]
for x in l:
    if x < 10 # avoid infinite loop
         l.append(x+1)
    print x

此代码正确,并且与您使用的代码相似。 输出是预期的1..10。 在for循环上添加项目是可以的(或在当前迭代器位置之后插入项目)。

现在尝试使用相同的示例,但要插入一个:

l = [1]
for x in l:
    if x < 10 # avoid infinite loop
         l.insert(0,x+1)
    print x

这次,您将陷入无限循环。 原因是for循环将始终检查下一个项目,并且由于我们在开始处插入x,因此被检查的项目将始终等于1。在当前迭代器位置之前插入项目通常是不好的。

最后检查此示例:

l = [1,2,3,4,5]
for x in l:
     print x
     l.remove(x)

此函数的输出将与预期的输出1、2、3、4、5相差1,3,5。 因此,在当前迭代器之前删除项目也是不好的。

为了简化起见,我们只能说应该避免在循环时更改列表的内容,除非您确切地知道自己在做什么以及它可能对输出造成什么影响。

将列表附加到要迭代的列表是安全的。 如果您的代码审阅者不愿意接受,或者对您仍然感到困惑,则可以使用两阶段方法:

paths = [blah blah]
next_paths = []
while paths:
    for path in paths:
        if something_or_other:
            next_paths.append(blah)
    paths = next_paths
    next_paths = []

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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