python - 内部循环不覆盖全局变量

时间:2015-02-02 11:06:56

标签: python

这是有史以来最愚蠢的问题之一!

我有一个for循环:

inner_step = 0
for i, v in enumerate(['a','b'], start=1 if inner_step == 0 else (inner_step+1)):
     print str(i) + ': ' + v
     for k, m in enumerate(['1','2'], start=i+1):
         print str(k) + ': ' + m
         inner_step = k

我希望

1: a
2: 1
3: 2
4: b
5: 1
6: 2

但我正在

1: a
2: 1
3: 2
2: b
3: 1
4: 2
显然,inner_step没有被内循环覆盖。我究竟做错了什么?

4 个答案:

答案 0 :(得分:2)

您可以使用itertools.count跟踪计数

from itertools import count

step = count(1)
for v in ['a', 'b']:
    print(str(next(step)) + ': ' + v)
    for m in ['1', '2']:
        print(str(next(step)) + ': ' + m)

1: a
2: 1
3: 2
4: b
5: 1
6: 2

答案 1 :(得分:1)

简化的第一步可能是这个(虽然距离pythonic解决方案还很远):

c = 1
for v in ['a','b']:
    print str(c) + ': ' + v
    c += 1
    for m in ['1','2']:
        print str(c) + ': ' + m
        c += 1

答案 2 :(得分:1)

每次迭代后都不会更新外部循环迭代器。 enumerate()对象只创建一次

保持一个明确的计数器在循环中更新:

step = 0
for v in ['a','b']:
     step += 1
     print '{}: {}'.format(step, v)
     for m in['1','2']:
         step += 1
         print '{}: {}'.format(step, m)

或使用计算枚举数字中的数字:

for outer, v in enumerate(['a','b']):
     print '{}: {}'.format(outer * 3 + 1, v)
     for inner, m in enumerate(['1','2']):
         print '{}: {}'.format(outer * 3 + 2 + inner, m)

两者都产生所需的输出:

>>> step = 0
>>> for v in ['a','b']:
...      step += 1
...      print '{}: {}'.format(step, v)
...      for m in['1','2']:
...          step += 1
...          print '{}: {}'.format(step, m)
... 
1: a
2: 1
3: 2
4: b
5: 1
6: 2
>>> for outer, v in enumerate(['a','b']):
...      print '{}: {}'.format(outer * 3 + 1, v)
...      for inner, m in enumerate(['1','2']):
...          print '{}: {}'.format(outer * 3 + 2 + inner, m)
... 
1: a
2: 1
3: 2
4: b
5: 1
6: 2

答案 3 :(得分:1)

这似乎是发电机的一个很好的应用。这里序列生成代码与枚举和打印代码分开,这使得可以在其他地方重用序列生成代码。

def expand(seq1, seq2):
    for outer in seq1:
        yield outer
        for inner in seq2:
            yield inner

for i, v in enumerate(expand(['a','b'], ['1','2']), start=1):
    print("{}: {}".format(i, v))

1: a
2: 1
3: 2
4: b
5: 1
6: 2

# or just pass the items to expand() in strings
for i, v in enumerate(expand('abc', '123'), start=1):
    print("{}: {}".format(i, v))

1: a
2: 1
3: 2
4: 3
5: b
6: 1
7: 2
8: 3
9: c
10: 1
11: 2
12: 3

expand()也可以作为普通函数实现,该函数构造并返回序列中的本地项目列表,但是,此生成器函数更清晰(不需要本地列表),并且更有效地扩展长序列。