在嵌套的while循环中覆盖迭代器时,for i in range()
会发生什么?例如,为什么以下代码段会提供不同的输出?当我在while循环中更改变量i
和j
的名称时,代码段的行为与我预期的一样。但是,当while循环覆盖i
和j
时,for
循环会受到影响。在for
可预测的情况下覆盖其迭代器时,while
循环的结果行为是什么?
(a)中
for i in range (0,3):
for j in range (0,3):
print "after nested for i,j",i,j
counter = 0
while counter < 3:
counter += 1
i = counter
j = counter
有o / p:
after nested for i,j 0 0
after nested for i,j 3 1
after nested for i,j 3 2
after nested for i,j 1 0
after nested for i,j 3 1
after nested for i,j 3 2
after nested for i,j 2 0
after nested for i,j 3 1
after nested for i,j 3 2
(b)(与while
评论相同的代码)
for i in range (0,3):
for j in range (0,3):
print "after nested for i,j",i,j
有o / p
after nested for i,j 0 0
after nested for i,j 0 1
after nested for i,j 0 2
after nested for i,j 1 0
after nested for i,j 1 1
after nested for i,j 1 2
after nested for i,j 2 0
after nested for i,j 2 1
after nested for i,j 2 2
答案 0 :(得分:2)
你的术语有点不对劲。在for循环中,您无法访问迭代器。迭代器在幕后隐藏。以下循环结构是等效的。
for i in range(10):
print(i)
it = iter(range(10)):
while True:
try:
i = next(it)
except StopIteration:
break
print(i)
正如您所见,迭代器对象(it
)在for循环中保持隐藏状态。可以在for循环中公开迭代器,但这是一个不同的问题。
您所谈论的是存储迭代元素的名称。如果您在循环过程中写过该名称,那么在下一次迭代开始时将忽略该值。环。这在循环结构的while版本中很容易看到,其中第一件事就是为名称i
分配了iterator.whil返回的下一个元素
我不确定代码的用途,但可以更改正在使用的迭代器的状态。为此,您必须写一个coroutine。协程是一个能够接受输入的专用发生器。
def generator_range(start, end, step=1):
"Simplified version of the range/xrange function written as a generator."
counter = start
while counter < end:
yield counter
counter += step
def coroutine_range(start, end, step=1):
"Special version of range that allows the internal counter to set."
counter = start
while counter < end:
sent = yield counter
if sent is None:
counter += step
else:
counter = sent
对于简单范围用法,生成器版本的行为相同。
例如
assert list(range(0, 10)) == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
assert list(range(0, 10)) == list(generator_range(0, 10))
assert list(range(0, 10)) == list(coroutine_range(0, 10))
但是我们可以用协程做更复杂的循环算法。
例如
# skip numbers in range 3-7 inclusive
l = []
co = coroutine_range(0, 10)
item_to_send = None
while True:
try:
i = co.send(item_to_send)
# if item_to_send is None then the above is the same as next(co)
item_to_send = None
except StopIteration:
break
if 3 <= i <= 7:
item_to_send = 8
else:
l.append(i)
assert l == [0, 1, 2, 8, 9]
答案 1 :(得分:1)
我认为这确实是一个变量范围的问题。 i
和j
位于本地函数名称空间中。虽然循环不会创建新的命名空间,所以在代码片段中
while len(list) < 2:
i = i
j = j
i
和&#39; j&#39;仍然是本地命名空间中的相同变量,您所做的就是将它们重新分配给自己。您没有创建新的i
或j
。它无害,但应删除这些任务。
稍后,在while
循环的底部,当你执行
i = PixelCoord[Lightest[1]][0]
j = PixelCoord[Lightest[1]][1]
您将本地函数命名空间中的i
和j
重新分配给for
循环中的迭代值。 j
相对良性,因为您返回内部for
循环并且j
被重新分配下一个迭代值。但这对x
来说是一个问题,因为它会保留更改的值,直到再次到达外部for
。
您可以通过几个打印语句清楚地看到问题
for i in range (1,array.shape[0]-1):
print('outer for, i is', i)
for j in range (1,array.shape[1]-1):
print('inner for, i and j are', i, j)
解决方案是使用不同的变量名称。
答案 2 :(得分:0)
如果我清楚你的问题,那么这就是解决方案:
函数中定义的变量具有函数范围,仅在函数体中可见。 您可以在不同的功能中使用相同的名称。
代码1:
def VAR1():
var = 'foo'
def inner():
var = 'bar'
print 'inside function, var is ', var
inner()
print 'outside function, var is ', var
VAR1()
输出:
inside function, var is bar
outside function, var is foo
但在单个函数中,变量是本地的。您不能在不同的地方使用相同的名称
代码1:
def VAR():
var = 'foo'
if True:
var = 'bar'
print 'inside if, var is ', var
print 'outside if, var is ', var
VAR()
输出:
inside if, var is bar
outside if, var is bar
答案 3 :(得分:-1)
这说明了case(a)
:
for i in range(0,2):
for j in range(0,2):
print(i,j)
i = 'new-i'
j = 'new-j'
print(' ', i,j)
输出:
0 0 # i and j set by the for statements
new-i new-j # i and j set by the inner assignments
new-i 1 # new j set by its for; i unchanged
new-i new-j
1 0 # new i and j set by for
new-i new-j
new-i 1
new-i new-j
i
和j
变量没有什么特别之处,只是它们在各自的循环开始时获得新值。在循环之后,i
和j
将在循环中包含其最后一个值,在本例中为new-i
和new-j
。
对于像这样的简单循环,你可以随心所欲地调整i
的值,并且它不会弄乱迭代(即for
的动作声明)。但由于它可能会使您和您的算法(以及您的读者)感到困惑,因此重新分配for
迭代变量通常不是一个好主意。
要将迭代变量与while
循环中的更改完全分开,您需要定义如下函数:
def foo(i,j):
print("after nested for i,j",i,j)
counter = 0
while counter < 3
counter += 1
i = counter
j = counter
for i in range(3):
for j in range(3):
foo(i,j)
制造
after nested for i,j 0 0
after nested for i,j 0 1
...
after nested for i,j 2 1
after nested for i,j 2 2
如果另一方面,您希望内部while
中的更改控制i
的迭代,您还需要在外部循环中使用while
:
i = 0
while i<3:
j = 0
while j<3:
print("after nested for i,j",i,j)
counter = 0
while counter < 3:
counter += 1
i = counter
j = counter
只打印一次(i
和j
都跳转到3)