>>> def countdown(n):
print('count down from {0}'.format(n))
while n > 0 :
yield n
n -= 1
... ... ... ... ...
>>> x=countdown(5)
print('x is set')
for i in x:
print(i)>>> x is set
>>> ...
...
count down from 5
5
4
3
2
1
>>> x
<generator object countdown at 0x100557b90>
>>> x=countdown(5)
>>> x
<generator object countdown at 0x100557c30>
>>> next(x)
count down from 5
5
>>> next(x)
4
>>> next(x)
3
>>> next(x)
2
>>> next(x)
1
>>> next(x)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>> import time
def follow(file):
file.seek(0,2)
while True:
line = file.readline()
if not line:
time.sleep(0.1)
continue
yield line
logfile=open('a')
for line in follow(logfile):
print("{0}".format(line),end="")>>> ... ... ... ... ... ... ... ... >>> >>> >>> ...
...
b
last
^CTraceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 6, in follow
KeyboardInterrupt
我们在另外的shell里
echo b >> a
echo last >> a
就可以让tail -f 的程序输出。
生成式组成管道流水线
生成器作为管道: 将上个生成器的输出作为下一个生成器的输出,就构成了一个管道
(管道是unix 下的一种进程间通讯工具,程序可以将自己的输出数据作为后一个程序的输入数据
比如:ls -l命令输出的文件列表:
lymatoMacBook-Pro:co ly$ ls -l
total 56
-rw-r--r-- 1 ly staff 43 Feb 2 15:27 a
-rw-r--r-- 1 ly staff 0 Feb 1 23:21 a.log
-rw-r--r-- 1 ly staff 172 Feb 2 10:01 countdown.py
-rwxr-xr-x 1 ly staff 9056 Feb 2 13:52 d
-rw-r--r-- 1 ly staff 606 Feb 2 14:06 d.c
-rw-r--r-- 1 ly staff 271 Feb 1 23:46 tailf.py
我们使用管道对这个数据按文件大小排序:
lymatoMacBook-Pro:co ly$ ls -l | sed 1d | sort -nk5
-rw-r--r-- 1 ly staff 0 Feb 1 23:21 a.log
-rw-r--r-- 1 ly staff 43 Feb 2 15:27 a
-rw-r--r-- 1 ly staff 172 Feb 2 10:01 countdown.py
-rw-r--r-- 1 ly staff 271 Feb 1 23:46 tailf.py
-rw-r--r-- 1 ly staff 606 Feb 2 14:06 d.c
-rwxr-xr-x 1 ly staff 9056 Feb 2 13:52 d
ls 的输出经由管道,由sed 和sort 过滤与重组以后,输出)
我们可以通过将yield 表达式作为下一个表达式的输出构成一个流水线:
import time
def follow(file):
file.seek(0,2)
while True:
line = file.readline()
if not line:
time.sleep(0.1)
continue
yield line
logfile=open('a')
loglines=follow(logfile)
def search(pattern, lines):
for line in lines:
if pattern in line:
yield line
pylines = search('python', loglines)
for pyline in pylines:
print("{0}".format(pyline),end="")
follow的输入被search 当作输入流过滤,就有了 tailf -f a | grep python的效果
lymatoMacBook-Pro:co ly$ python3 pipeline.py
python
we mention python
we mention python in line again
协程(coroutine)
yield可以作为(右值),从而变成协程
def search(pattern):
print ('looking for {0}'.format(pattern))
while True:
line = (yield)
if pattern in line:
print(line)
@coroutine
def search(pattern):
print (‘looking for {0}’.format(pattern))
try:
while True:
line = (yield)
if pattern in line:
print(line)
except GeneratorExit:
print(‘generator closed’)
一个讨厌的例子:
>>> def countdown(n):
print("Counting down from {0}".format( n))
while n >= 0:
newvalue = (yield n)
# If a new value got sent in, reset n with it
if newvalue is not None:
n = newvalue
else:
n -= 1
c = countdown(5)
for n in c:
print(n)
if n == 5:
c.send(3)