1. 程式人生 > >Python全棧之路Day21

Python全棧之路Day21

引用 ror iter 一次函數 art 異常 logs generator nes

初次編輯2017年10月27日,星期五

摘要
一. 上節課復習
二. 叠代器
三. 生成器
四. 協程函數
作業
今日總結

摘要

引用:Alex

  1. 叠代器
  2. 生成器
  3. 協程函數

一. 上節課復習

  1. 裝飾器
    1. 無參裝飾器
    2. 有參裝飾器
  2. 裝飾器打印原函數信息
import time
from functools import wraps        #註意這個
def timmer(func):
    @wraps(func)        #還有這個
    def wrapper():
        start_time = time.time()
        func()
        stop_time = time.time()
        print(‘run time is %s ‘ % (stop_time - start_time))
    return wrapper

@timmer        #index=timmer(index)
def index():
    ‘come from index‘
    print(‘welcome to oldboy‘)

index()        #wrapper()
print(index.__doc__)        #.__doc__打印函數描述信息,具體不是很了解

二. 叠代器

  1. 可叠代的
    • 只要對象本身有__iter__方法,那它就是可叠代的
  2. 叠代器
    • i = a.iter() #i 即為叠代器
    • 可通過__next__ 進行取值
b = {‘a‘:1,‘b‘:2,‘c‘:3}
i = iter(b)
while True:
    print(next(i))

#註意:此方法會while會無限循環,報錯異常 StopIteration
  1. 異常捕捉
b = {‘a‘:1,‘b‘:2,‘c‘:3}
i = iter(b)
while True:
    try:        #註意此行
        print(next(i))
    except StopIteration:        #and this
        break    # and this
  1. for 循環機制
for key in d:    #d即為d.__iter__() 叠代器放入原位置
    print(key)    #並且for循環具有異常捕捉的功能
  1. for 循環實現叠代器
b = {‘a‘:1,‘b‘:2,‘c‘:3}
for i in b:
    print(i)
  1. 為什麽要用叠代器
    • 優點
      1. 叠代器提供了一種不依賴於索引的取值方式,這樣就可以遍歷那些沒有索引的可叠代對象了(字典、集合、文件)
      2. 叠代器與列表相比,叠代器是惰性計算的,更省內存(叠代器在內存中同一時刻只有一個值)
    • 缺點
      1. 無法獲取叠代器的長度,使用不如列表索引取值靈活
      2. 一次性的,只能往後取值,不能倒著取值
  2. 查看可叠代對象與叠代器對象
from collections import Iterable,Iterator

s = ‘hello‘
l = [1,2,3]
t = (1,2,3)
d = {‘a‘:1}
set1 = (1,2,3,4)
f = open(‘a.txt‘)

s.__iter__()
l.__iter__()
t.__iter__()
d.__iter__()
set1.__iter__()
f.__iter__()
                                                    #Iterable 為可叠代的
print(isinstance(s,Iterable))        #isinstance()  函數來判斷一個對象是否是一個已知的類型,類似 type()。
print(isinstance(l,Iterable))
print(isinstance(t,Iterable))
print(isinstance(d,Iterable))
print(isinstance(set1,Iterable))
print(isinstance(f,Iterable))
  1. 查看是否是叠代器
print(isinstance(s,Iterator))        #Iterator 為叠代器
print(isinstance(l,Iterator))
print(isinstance(t,Iterator))
print(isinstance(d,Iterator))
print(isinstance(set1,Iterator))
print(isinstance(f,Iterator))

三. 生成器

  1. 定義:生成器就是一個函數,這個函數內包含有yield這個關鍵字,可以將函數變成具有序列性,返回多個值
  2. 生成器與return有何區別
    • return只能返回一次函數就徹底結束了,而yield能返回多次值
  3. yield到底幹了什麽事
    • yield把函數變成生成器(生成器其實就是叠代器)(yield將__next__和__iter__封裝到函數內部)
    • 用return返回只能返回一次,而yield返回多次
    • 函數在暫停以及繼續下一次運行時的狀態是由yield保存
def test():
    print(‘one‘)
    yield 1
    print(‘two‘)
    yield 2
    print(‘three‘)
    yield 3

g = test()        #無輸出,此時g為生成器,即把函數變成一個叠代器
print(g)        #<generator object test at 0x00000000027E91A8>
res = next(g)    #one        next觸發生成器的執行
print(res)        #1
  1. yield具體應用
def countdown(n):
    print(‘start countdown‘)
    while n >0:
        yield n
        n -= 1
    print(‘done‘)

g= countdown(5)

print(next(g))        #start countdown    5
print(next(g))        #4
print(next(g))        #3
print(next(g))        #2
print(next(g))        #1
print(next(g))        #done    #會報錯

#for循環寫法
for i in g:
    print(i)

#while循環寫法
while True:
    try:
        print(next(g))
    except    StopIteration:
        break
  1. 生成器應用
#惰性計算
def func():
    n = 0
    while True:
        yield n
        n += 1

f = func()
print(next(f))
  1. tail命令的最基本實現
import time
def tail(file_path):
    with open(file_path,‘r‘) as f:
        f.seek(0,2)                    #光標移到最後
        while True:
                line = f.readline()            #讀這一行
                if not line:
                        time.sleep(0.5)
                        continue
                else:
                        print line,        #print 輸出光標不換行

tail(‘/tmp/a.txt‘)
  1. tail命令通過生成器實現(python2)
import time
def tail(file_path):
    with open(file_path,‘r‘) as f:
        f.seek(0,2)                    #光標移到最後
        while True:
                line = f.readline()            #讀這一行
                if not line:
                        time.sleep(0.5)
                        print ‘=======‘
                        continue
                else:
                        yield line

g = tail(‘/tmp/a.txt‘)        #函數變成一個生成器

for line in g:
        print line,
  1. grep命令通過生成器實現(python2)
import time
def tail(file_path):
    with open(file_path,‘r‘) as f:
        f.seek(0,2)                    #光標移到最後
        while True:
                line = f.readline()            #讀這一行
                if not line:
                        time.sleep(0.5)
                        continue
                else:
                        yield line

g = tail(‘/tmp/a.txt‘)

for line in g:
        if ‘error‘ in line:
                print line,
  1. grep命令通過生成器實現且有水流概念
import time
def tail(file_path):
    with open(file_path,‘r‘) as f:
        f.seek(0,2)                    #光標移到最後
        while True:
                line = f.readline()            #讀這一行
                if not line:
                        time.sleep(0.5)
                        continue
                else:
                        yield line

def grep(pattern,lines):                #pattern 為grep所抓取的 lines為輸入源
        for line in lines:
                if pattern in line:
                        print line,

g = tail(‘/tmp/a.txt‘)
grep(‘error‘,g)
  1. tail、grep命令最終版
import time
#定義階段:定義兩個生成器函數
def tail(file_path):
    with open(file_path,‘r‘) as f:
        f.seek(0,2)                    #光標移到最後
        while True:
                line = f.readline()            #讀這一行
                if not line:
                        time.sleep(0.5)
                        continue
                else:
                        yield line

def grep(pattern,lines):                #pattern 為grep所抓取的 lines為輸入源
        for line in lines:
                if pattern in line:
                        yield line

#調用階段:得到倆生成器對象
g1 = tail(‘/tmp/a.txt‘)
g2 = grep(‘error‘,g1)

#使用階段:next觸發執行g2生成器函數
for i in g2:
        print i,

四. 協程函數

  1. 吃包子
def eater(name):
    print(‘%s start to eat food ‘% name)
    food_list = []
    while True:
        food = yield food_list
        print(‘%s get %s, to start eat ‘% (name, food))
        food_list.append(food)
    print(‘Done‘)

e = eater(‘鋼蛋‘)

print(next(e))
print(e.send(‘包子‘))
print(e.send(‘韭菜包子‘))    #send 等同於next 有返回值,但是會把後面的參數傳給當前行的yield
print(e.send(‘餡餅‘))

作業

今日總結

  1. 待整理

Python全棧之路Day21