I was looking for code to spin a cursor in the terminal and found this. I was wondering what was happening in the code. In particular for c in spinning_cursor():
I've never seen this syntax. Is it because I am returning one element from a generator at a time with yield
, and this is assigned to c? Any other examples of this for x in y() use?
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')
Using yield
turns a function into a generator. A generator is a specialized type of iterator. for
always loops over iterables, taking each element in turn and assigning it to the name(s) you listed.
spinning_cursor()
returns a generator, the code inside spinning_cursor()
doesn't actually run until you start iterating over the generator. Iterating over a generator means the code in the function is executed until it comes across a yield
statement, at which point the result of the expression there is returned as the next value and execution is paused again.
The for
loop does just that, it'll call the equivalent of next()
on the generator, until the generator signals it is done by raising StopIteration
(which happens when the function returns). Each return value of next()
is assigned, in turn, to c
.
You can see this by creating the generator on in the Python prompt:
>>> 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) '|'
This specific generator never returns, so StopIteration
is never raised and the for
loop will go on forever unless you kill the script.
A far more boring (but more efficient) alternative would be to use itertools.cycle()
:
from itertools import cycle spinning_cursor = cycle('/-\|')
In Python, the for statement lets you iterate over elements.
According the documentation :
Python’s for statement iterates over the items of any sequence (a list or a string), in the order that they appear in the sequence
Here, the element will be the return value of spinning_cursor()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With