python 新手:j 在范围内

python newbie: for j in range

最近刚开始学习python。看书的时候,发现有一行代码看不懂。 请参阅 print_progression() 方法下的第 46 行,print(' '.join(str(next(self)) for j in range(n))).

class Progression:
    '''Iterator producing a generic progression.
    Default iterator produces the whole number, 0, 1, 2, ...
    '''

def __init__(self, start = 0):
    '''
    Initialize current to the first value of the progression.
    '''
    self._current = start

def _advance(self):
    '''
    Update self.current to a new value.
    This should be overriden by a subclass to customize progression.
    By convension, if current is set to None, this designates the
    end of a finite progression.
    '''
    self._current += 1

def __next__(self):
    '''
    Return the next element, or else raise StopIteration error.
    '''
    # Our convention to end a progression
    if self._current is None:
        raise StopIteration()
    else:
        # record current value to return
        answer = self._current
        # advance to prepare for next time
        self._advance()
        # return the answer
        return answer

def __iter__(self):
    '''
    By convention, an iterator must return itself as an iterator.
    '''
    return self

def print_progression(self, n):
    '''
    Print next n values of the progression.
    '''
    print(' '.join(str(next(self)) for j in range(n)))


class ArithmeticProgression(Progression): # inherit from Progression
    pass

if __name__ == '__main__':
    print('Default progression:')
    Progression().print_progression(10)

'''Output is
Default progression:
0 1 2 3 4 5 6 7 8 9 10'''

我不知道 next(self) 和 j 是如何工作的。

  1. 我觉得应该是str(Progression.next())。 (已解决)

  2. 我到处都找不到 j。什么是j?为什么不使用 while 循环,例如 while Progression.next() <= range(n)?

我最后的想法应该是

print(' '.join(str(next(self)) while next(self) <= range(n)))

拯救这个新手。

提前致谢!

欢迎来到 python 社区!这是一个很好的问题。在 python 中,与在其他语言中一样,有很多方法可以做事。但是当您遵循 python 社区所做的约定时,这通常被称为 "pythonic" 解决方案。方法 print_progression 是用户定义数据结构迭代的常见 pythonic 解决方案。在上面的例子中,让我们首先解释代码是如何工作的,然后解释为什么我们要那样做。

您的 print_progression 方法利用了您的 Progression class 通过实施 nextiter 来实施迭代协议这一事实 dunder/magic 方法。因为这些已经实现,你可以在内部迭代你的 class 实例,就像 next(self) 所做的那样,在外部 next(Progression()) 这正是你在 1 号上得到的。因为这个协议是已经实现,这个 class 可以在任何客户端的任何内置迭代器和生成器上下文中使用!那是一个多态的解决方案。它也只是在内部使用,因为您不需要以两种不同的方式进行操作。

现在是未使用的 J 变量。他们只是在使用它,所以他们可以使用 for 循环。仅使用 range(n) 只会 return 一个可迭代的但不会对其进行迭代。我不太同意作者使用名为 J 的变量,通常更常见的是表示一个未使用的变量,只是因为它需要作为单个下划线使用。我更喜欢这个:

 print(' '.join(str(next(self)) for _ in range(n)))

我认为@csevier ,但我不确定第二个问题是否根据您的评论清楚地回答了您,所以我将尝试换个角度。

假设你做到了:

for x in range(10):
    print(x)

这是可以理解的 - 您创建了一个列表 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 并依次打印了该列表中的每个值。现在假设我们只想打印 "hello" 10 次;好吧,我们可以非常简单地修改我们现有的代码:

for x in range(10):
    print(x)
    print('hello')

嗯,但是现在 x 打乱了我们的输出。没有:

do this 10 times:
    print('hello')

语法。我们可以使用 while 循环,但这意味着要定义一个额外的计数器:

loop_count = 0
while loop_count < 10:
    print('hello')
    loop_count += 1 

那是行李。因此,更好的方法是只使用 for x in range(10): 而不必费心做 print(x);这个值是为了让我们的循环工作,而不是因为它在任何其他方面都有用。这与 j 相同(虽然我在示例中使用了 x,因为我认为您更有可能在教程中遇到它,但您几乎可以使用任何您想要的名称)。此外,while 循环通常用于可以无限期 运行 的循环,而不是用于迭代具有固定大小的对象:参见 here