对于y()中的x:这是如何工作的?

我正在寻找代码在terminal中旋转光标,并发现这一点。 我想知道代码中发生了什么。 特别是for c in spinning_cursor():我从来没有见过这种语法。 是因为我一次从产生器返回一个元素,并且这个元素被分配给c? 在y()中使用x的这个任何其他的例子?

 import sys import time def spinning_cursor(): cursor='/-\|' i = 0 while 1: yield cursor[i] i = (i + 1) % len(cursor) for c in spinning_cursor(): sys.stdout.write(c) sys.stdout.flush() time.sleep(0.1) sys.stdout.write('\b') 

使用yield将函数转换为一个生成器 。 生成器是一种特殊types的迭代器 。 总是循环迭代,依次取每个元素,并将其分配给您列出的名称。

spinning_cursor()返回一个生成器,在您开始迭代生成器之前, spinning_cursor()中的代码实际上并不运行。 对一个生成器进行迭代意味着函数中的代码被执行,直到遇到一个yield语句,此时expression式的结果作为下一个值返回,执行再次被暂停。

for循环就是这样做的,它会调用生成器上的next()的等价物,直到生成器通过提高StopIteration (在函数返回时发生)来发出信号。 next()每个返回值依次分配给c

您可以通过在Python提示符下创build生成器来看到这一点:

 >>> def spinning_cursor(): ... cursor='/-\|' ... i = 0 ... while 1: ... yield cursor[i] ... i = (i + 1) % len(cursor) ... >>> sc = spinning_cursor() >>> sc <generator object spinning_cursor at 0x107a55eb0> >>> next(sc) '/' >>> next(sc) '-' >>> next(sc) '\\' >>> next(sc) '|' 

这个特定的生成器永远不会返回,所以StopIteration永远不会被提出, for循环将永远持续下去,除非你杀死脚本。

在Python中,for语句允许您遍历元素。

根据文件 :

Python的for语句按照它们出现在序列中的顺序迭代任何序列(一个列表或一个string)的项目

在这里,元素将是spinning_cursor()的返回值。

for c in spinning_cursor()语法中的for c in spinning_cursor()for-each循环。 它将遍历由spinning_cursor()返回的迭代器中的每个项目。

循环的内部将会:

  1. 将字符写入标准输出并刷新,以便显示。
  2. 睡十分之一秒
  3. \b ,这被解释为一个退格(删除最后一个字符)。 注意这发生在循环的结尾,所以它不会在第一次迭代期间被写入,并且它在步骤1中共享flush调用。

spinning_cursor()将返回一个生成器 ,直到开始迭代,它才会真正运行。 它看起来像循环通过'/-\|' ,为了,永远。 这就像有一个无限的列表来遍历。

所以,最终的输出将是一个ASCII微调。 你会看到这些字符(在同一个地方)重复,直到你杀死脚本。

 / - \ | 

Martijn Pieters的解释非常好。 以下是您在问题中使用的相同代码的另一个实现。 它使用itertools.cycle产生与spinning_cursor相同的结果。 itertools充满了迭代器和函数的优秀例子来帮助创build自己的迭代器。 这可能会帮助你更好地理解迭代器。

 import sys, time, itertools for c in itertools.cycle('/-\|'): sys.stdout.write(c) sys.stdout.flush() time.sleep(0.1) sys.stdout.write('\b') 

spinning_cursor函数返回一个iterable(一个来自yield的生成器)。

 for c in spinning_cursor(): 

会是一样的

  for i in [1, 2, 3, 4]: