c迭代器與生成器

一:迭代器python

1.什麼是迭代?linux

  1.重複   2.下一次重複是基於上一次的結果數據結構

 

# l=['a','b','c','d'] # count=0 # while count < len(l): # print(l[count]) #count的值基於上一次結果,因此是迭代
# count+=1

 

2.迭代器協議app

  指:對象必須提供一個next方法,執行該方法要麼返回迭代中的下一項,要麼就引發一個StopIteration異常,以終止迭代 (只能日後走不能往前退)。ide

   python 爲了提供一種不依賴索引的迭代方式
  以obj=[1,2,3,,4,5]爲例:
       python會爲一些對象內置.__iter__方法,可以.__iter__的都是能夠成爲可迭代對象.
         若是咱們obj.__iter__()後獲得一個結果就是迭代器。  迭代器既有.__iter__ 方法又有 .__next__方法.
 

  迭代器的優勢:
    1.提供了一種不依賴索引的迭代方式
    2.惰性計算,節省內存

  迭代器的缺點:
    1.取值不如按照索引取值的方便
    2.只能前進,不能後退
    3.沒法獲取長度函數

判斷是否爲可迭代對象或者迭代器對象的方法:測試

以a=[1,2,3,4]爲例:
方法一:
   obj=a.__iter__()     說明他是可迭代對象,obj成爲迭代器
   obj.__next__()       說明obj是迭代器對象
方法二: 
   from collections import Iterable,Iterator    #調用相應模塊,測試是否爲可迭代對象或者迭代器對象
    print(isinstance(a,Iterable))   #判斷是否爲可迭代對象,若是是則返回True
       print(isinstance(a,Iterator))   #判斷是否爲迭代器對象,若是是則返回True
# # from collections import Iterable,Iterator # # print(isinstance(g,Iterator)) #可判斷是夠爲迭代器對象
# def countdown(n): # print('starting countdown') # # while n > 0: # yield n # n-=1 # print('stop countdown') # g=countdown(5)

# print(g.__next__()) # print(g.__next__()) # for i in g: # print(i)
View Code

 3 迭代器spa

  在介紹迭代器以前,咱們先來了解一下容器這個概念。code

    容器是一種把多個元素組織在一塊兒的數據結構,容器中的元素能夠逐個地迭代獲取。簡單來講,就比如一個盒子,咱們能夠往裏面存放數據,也能夠從裏面一個一個地取出數據。在python中,屬於容器類型地有:list,dict,set,str,tuple.....。容器僅僅只是用來存放數據的,咱們日常看到的 l = [1,2,3,4]等等,好像咱們能夠直接從列表這個容器中取出元素,但事實上容器並不提供這種能力,而是可迭代對象賦予了容器這種能力。對象

   說完了容器,咱們在來談談迭代器。迭代器與可迭代對象區別在於:__next__()方法。

  咱們能夠採用如下方法來驗證一下:

from collections import Iterator

f = open('a.txt')
i = 1
s = '1234'
d = {'abc':1}
t = (1, 2, 344)
m = {1, 2, 34, }

print(isinstance(i,Iterator))
print(isinstance(s,Iterator))
print(isinstance(d,Iterator))
print(isinstance(t,Iterator))
print(isinstance(m,Iterator))
print(isinstance(f,Iterator))

########輸出結果##########
False
False
False
False
False
True
View Code

  結果顯示:除了文件對象爲迭代器,其他均不是迭代器

  下面,咱們進一步來驗證一下:

print(hasattr(i,"__next__"))
print(hasattr(s,"__next__"))
print(hasattr(d,"__next__"))
print(hasattr(t,"__next__"))
print(hasattr(m,"__next__"))
print(hasattr(f,"__next__"))

#######結果###########
False
False
False
False
False
True
View Code

從輸出結果能夠代表,迭代器與可迭代對象僅僅就是__next__()方法的有無

——————--模擬linux中的taif -f a.txt |grep 'error'  |grep '404'
 
'模擬linux中'
#tail -f a.txt
import time
def tail(filepath,encoding='utf-8'):
    with open(filepath,encoding=encoding) as f:
        f.seek(0,2)
        while True:
            line=f.readline()
            if line:
                print(line,end='')
                # yield line
            else:
                time.sleep(0.5)

tail('b.txt')

# for i in g:
#     print(i)

#tail -f a.txt |grep 'error'

# def grep(lines,pattern):
#     for line in lines:
#         if pattern in line:
#             # print(line,end='')
#             yield line

# g=tail('a.txt')
# print(g)

# grep(g,'error')

# tail -f a.txt |grep 'error' |grep '404'

# g1=tail('a.txt')
# g2=grep(g1,'error')
# g3=grep(g2,'404')
# for i in g3:
#     print(i)
View Code

 

4   for循環
  for循環的本質:循環全部對象,全都是使用迭代器協議

Tips:(字符串,列表,元組,字典,集合,文件對象)這些都不是可迭代對象,只不過在for循環式,調用了他們內部的__iter__方法,把他們變成了可迭代對象,

而後for循環調用可迭代對象的__next__方法去取值,並且for循環會捕捉StopIteration異常,以終止迭代.

   StopIteration異常:.__nex___執行後若是沒有返回值就會報此異常。

 

for item in g: 
    print(item)

 ###for執行in後面的對象g下面的.__iter__方法,獲得一個迭代器k,而後for循環自動k.__next__一次,將獲得的結果賦值給item.而後再iter一次變成迭代器賦值給item,直到沒有值輸出,出現stopiteration異常,for循環能夠捕捉到這個異常,而後終止這個循環。

for item in 8:
  print(item)
============結果================
TypeError:'int' object is not iterable ###數字是不可迭代對象,下面沒有.__iter__方法,因此報錯。

 

 

 

Try 可檢測異常:

l={'a':1,'x':2,'w':3,'z':4} l=l.__iter__()    #轉換成迭代器
while True: try:     #捕捉異常,檢測其下縮進的語句是否有異常
        i=l.__next__() print(i) except StopIteration:   #except檢測異常
        break
View Code

 

二:生成器(生成器的本質就是迭代器)

1.什麼是生成器

  能夠理解爲一種數據類型,這種數據類型自動實現了迭代器協議(其餘的數據類型須要調用本身內置的__iter__方法),因此生成器是可迭代對象。

  按照咱們以前所說的,迭代器必須知足兩個條件:既有__iter__(),又有__next__()方法。那麼生成器是否也有這兩個方法呢?答案是,YES。具體來經過如下代碼來看看。

 

def func():
    print("one------------->")
    yield 1
    print("two------------->")
    yield 2
    print("three----------->")
    yield 3
    print("four------------>")
    yield 4

print(hasattr(func(),'__next__'))
print(hasattr(func(),'__iter__'))

#########輸出結果###########
True
True
View Code

Python有兩種不一樣的方式提供生成器:

  1.函數體內包含有yield關鍵字,該函數的執行結果是生成器(generator).可是,使用yield語句而不是return語句返回結果。yield語句一次返回一個結果,在每一個結果中間,掛起函數的狀態,以便下次重它離開的地方繼續執行.

  2.生成器表達式:相似於列表推導,可是,生成器返回按需產生結果的一個對象,而不是一次構建一個結果列表 

既然生成器就是迭代器,那麼咱們是否是也能夠經過for循環來遍歷出生成器中的內容呢?看下面代碼.

def func():
    print("one------------->")
    yield 1
    print("two------------->")
    yield 2
    print("three----------->")
    yield 3
    print("four------------>")
    yield 4

for i in func():
    print(i)

#########輸出結果########
one------------->
1
two------------->
2
three----------->
3
four------------>
4
View Code

很顯然,生成器也能夠經過for循環來遍歷出其中的內容。

下面咱們來看看生成器函數執行流程:

def func():
    print("one------------->")
    yield 1
    print("two------------->")
    yield 2
    print("three----------->")
    yield 3
    print("four------------>")
    yield 4


g = func()  #  生成器 == 迭代器
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())
View Code

每次調用g.__next__()就回去函數內部找yield關鍵字,若是找獲得就輸出yield後面的值而且返回;若是沒有找到,就會報出異常。上述代碼中若是在調用g.__next__()就會報錯。Python使用生成器對延遲操做提供了支持。所謂延遲操做,是指在須要的時候才產生結果,而不是當即產生結果。這也是生成器的主要好處。

 

 生成器就是迭代器,只能前進不能後退,咱們看下這個例子:

#生成器函數補充
# def countdown(n):
#     while n > 0:
#         yield n
#         n-=1
#
# g=countdown(5)
# print(g.__next__())
# print(g.__next__())
#
# print('='*20)
# for i in g:
#     print(i)
#
# print('*'*20)
# for i in g:
#     print(i)

=======結果========
5
4
====================
3
2
1
********************
View Code

yiled與return的區別:

一個標準:
  yield和return類似可是一個函數內能夠有多個yield而函數中出現了多個return也只會對第一個return有效果
yield的功能:
  1. 與return相似,均可以返回值,不同在於,yield能夠返回多個值並且可暫停,再次執行可繼續下一步操做,return到了就中止不在繼續運行。
  2.爲封裝好的的函數可以使用__iter__和__next__方法,
  3.遵循迭代器的取值方式obj.__next__(),觸發函數的執行和函數的保存都是經過yeild保存的
 
=========================================================================================================================================
1.三元表達式
x=2
y=3

# if x > y:
#     print(x)
# else:
#     print(y)

# res='aaaaa' if x > y else 'bbbbbbb'   #三元表達式---->【 條件成立     條件  條件不成立】
#
# print(res)
View Code

2.列表解析<不能加else,條件成立的狀況下放到左邊。>

# l=[1,31,73,84,57,22]
# l_new=[]
# for i in l:
#     if i > 50:
#         l_new.append(i)
# print(l_new)
#列表解析
# res=[i for i in l if i > 50]
# print(res)
View Code

3.生成器表達式

#g=(i for i in range(100000000000000000000000000000))
#print (g)

#print(next(g))   ##next(g) == g.__next__()
#print(next(g))   ##next(g) == g.__next__()
相關文章
相關標籤/搜索