for y in range(y) in Python

3
这可能看起来像一个愚蠢的问题,但实际上我自己也被难住了。我试着写一个“金字塔”样式的代码,我成功了,但我不知道我是怎么做到的。金字塔的前半部分很明显,而第二半部分是我无意中写出来的,我也弄不清楚为什么这段代码能够正常运行。
以下是我的代码:
for x in range(5): # I understand why this loop works, its fairly simple
    for y in range(x+1):
        print(y, end='')
    print('')

for x in range(5):
    for y in range(y): # This is the part I can't seem to wrap my head around
        print(y, end='')
    print('')

输出结果为:
0
01
012
0123
01234
0123
012
01
0

我一直盯着它看,但不明白 for y in range(y) 是如何工作的。

4个回答

2
range对象描述了一个半开区间。这意味着它的上限不包括在内:
>>> 5 in range(5)
False

for循环只会对可迭代对象进行一次评估。重复使用可迭代对象的名称或参数不会影响循环。

>>> a = 3
>>> for b in range(a):
...     print(b, a)
...     a += 1  # does not extend the range!
0 3
1 4
2 5

那也意味着迭代变量在可迭代对象中使用是安全的。当循环分配给迭代变量时,可迭代对象已经被评估过了。
这意味着像 for y in range(y): 这样的结构将 a) 安全地分配给 y 而不改变当前迭代,并且 b) 迭代 y0y-1。换句话说,循环正常工作,但之后使 y 减少了一。
这种效果发生在第二个循环中: 每次运行 for y in range(y) 循环时,y 都会稳定减少1。外部循环只需运行足够多次以达到0。比较:
>>> y = 4
>>> while y:
...     print(y, ':', end='')
...     for y in range(y):
...         print(y, end='')
...     print('\t=>', y)
4 :0123 => 3
3 :012  => 2
2 :01   => 1
1 :0    => 0

0

你的代码中有一个变量y。在第一个块中,它被设置为1、2、3和4。该变量在第二个块中保留最后一个值。

你可以在这段代码中看到它

for x in range(5):
    for y in range(x+1):
        print(y, end='')
    print('')

print('Last y after first block: {}'.format(y)) # y has the value 4

for x in range(5):
    for y in range(y):
        print(y, end='') # y decreases in each iteration because range(y) goes from 0 through y-1 and y-1 is the last value
    print('')
    print('Last y after inner loop: {}'.format(y)) # y has the value y-1

y 在第一个代码块中创建,并一直存在到代码结束。


2
它还在第二个循环中使用 y 来减少自身。 - azro

0

Python的作用域规则很奇怪。单独使用,第二个循环将无法工作:

>>> for y in range(y): print(y)
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'y' is not defined

然而,由于您还有第一个循环,并且由于for循环不会创建自己的作用域,因此y从第一个循环中幸存下来,其最后一个值为6。

然后第二个循环是for y in range(6),但是y继续计数,因为range在右侧是排除的。


0

这是不必要的棘手。变量y之所以从4开始,是因为前面的循环(这是最好的不可靠假设和最坏的实现依赖)。再加上在第二个循环中将现有的y变量重新分配为y-1,使得跟踪变得非常困难。

一个更清晰的方法是使用与前一个循环相同的逻辑,但反向遍历x的值:

for x in range(5):       # forward loop
    for y in range(x+1):
        print(y, end='')
    print('')

for x in reversed(range(4)): # backward loop mirrors the previous one
    for y in range(x+1):
        print(y, end='')
    print('')

或者如果你喜欢使用一点数学,可以在单个循环中完成:

N = 5
for x in range(1-N,N):
    for y in range(N-abs(x)):
        print(y,end='')
    print()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接