对于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()
返回的迭代器中的每个项目。
循环的内部将会:
- 将字符写入标准输出并刷新,以便显示。
- 睡十分之一秒
- 写
\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]: