1. 程式人生 > >計算機基礎-----叠代器 和生成器

計算機基礎-----叠代器 和生成器

很快 中新 為我 spl pytho 調用 輸入 def ont

叠代器

1.1叠代器 和 可叠代對象

叠代器的本質 就是for循環調用的底層內置函數的運用

可叠代對象:字符串、列表、元組、字典、集合都是可叠代的對象

叠代器協議--必須要滿足兩點才可以叫做可叠代協議

: 內部實現了__iter__和__next__

1.2叠代器----iterator

通過代碼來理解

技術分享
‘‘‘
dir([1,2].__iter__())是列表叠代器中實現的所有方法,dir([1,2])是列表中實現的所有方法,都是以列表的形式返回給我們的,為了看的更清楚,我們分別把他們轉換成集合,
然後取差集。
‘‘‘
#print(dir([1,2].__iter__()))
#
print(dir([1,2])) print(set(dir([1,2].__iter__()))-set(dir([1,2]))) 結果: {__length_hint__, __next__, __setstate__}
View Code

叠代器中的三個方法的作用

技術分享
iter_l = [1,2,3,4,5,6].__iter__()
#獲取叠代器中元素的長度
print(iter_l.__length_hint__())
#根據索引值指定從哪裏開始叠代
print(*,iter_l.__setstate__(4))
#一個一個的取值
print(**,iter_l.__next__
()) print(***,iter_l.__next__())
View Code

在for循環中,就是在內部調用了__next__方法才能取到一個一個的值,,但是取不到值的時候會報錯

技術分享
經典  一眼就能看出來
l = [1,2,3,4]
l_iter = l.__iter__()
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)
item 
= l_iter.__next__() print(item)
View Code

內置函數:next和iter方法

技術分享
print(__next__ in dir(range(12)))  #查看‘__next__‘是不是在range()方法執行之後內部是否有__next__
print(__iter__ in dir(range(12)))  #查看‘__next__‘是不是在range()方法執行之後內部是否有__next__

from collections import Iterator
print(isinstance(range(100000000),Iterator))  #驗證range執行之後得到的結果不是一個叠代器

range函數的返回值是一個可叠代對象
View Code

生成器--沒有叠代協議但是還想要叠代

-- 自己生一個

2.1python自帶的生成器

  

1.生成器函數:常規函數定義,但是,使用yield語句而不是return語句返回結果。yield語句一次返回一個結果,在每個結果中間,掛起函數的狀態,以便下次重它離開的地方繼續執行

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

1.3 生成器Generator的本質:開發者自定義的生成器 ..惰性運算 ...節省內存..

1.4生成器函數: 一個包含yield關鍵字的函數就是一個 生成器函數, yield可以為我們從函數中返回值,但其又不同於return,return意味著程序結束 而其是程序停在那裏 需要調用的時候再調用 就可以繼續運行

技術分享
import time
def genrator_fun1():
    a = 1
    print(現在定義了a變量)
    yield a
    b = 2
    print(現在又定義了b變量)
    yield b

g1 = genrator_fun1()
print(g1 : ,g1)       #打印g1可以發現g1就是一個生成器
print(-*20)   #我是華麗的分割線
print(next(g1))
time.sleep(1)   #sleep一秒看清執行過程
print(next(g1))

初識生成器函數
View Code

代碼體現生成器不占內存

技術分享
import time
def genrator_fun1():
    a = 1
    print(現在定義了a變量)
    yield a
    b = 2
    print(現在又定義了b變量)
    yield b

g1 = genrator_fun1()
print(g1 : ,g1)       #打印g1可以發現g1就是一個生成器
print(-*20)   #我是華麗的分割線
print(next(g1))
time.sleep(1)   #sleep一秒看清執行過程
print(next(g1))

初識生成器函數
View Code

監控文件這點自己不是太懂記得問一下

技術分享
import time


def tail(filename):
    f = open(filename)
    f.seek(0, 2) #從文件末尾算起
    while True:
        line = f.readline()  # 讀取文件中新的文本行
        if not line:
            time.sleep(0.1)
            continue
        yield line

tail_g = tail(tmp)
for line in tail_g:
    print(line)

生成器監聽文件輸入的例子
View Code

列表推導式和生成器表達式

#老男孩由於峰哥的強勢加盟很快走上了上市之路,alex思來想去決定下幾個雞蛋來報答峰哥

egg_list=[雞蛋%s %i for i in range(10)] #列表解析

#峰哥瞅著alex下的一筐雞蛋,捂住了鼻子,說了句:哥,你還是給我只母雞吧,我自己回家下

laomuji=(雞蛋%s %i for i in range(10))#生成器表達式
print(laomuji)
print(next(laomuji)) #next本質就是調用__next__
print(laomuji.__next__())
print(next(laomuji))

峰哥與alex的故事

(老師總結的很好 我能看懂 )

#列表解析
sum([i for i in range(100000000)])#內存占用大,機器容易卡死
 
#生成器表達式
sum(i for i in range(100000000))#幾乎不占內存

總結:

1.把列表解析的[]換成()得到的就是生成器表達式

2.列表解析與生成器表達式都是一種便利的編程方式,只不過生成器表達式更節省內存

3.Python不但使用叠代器協議,讓for循環變得更加通用。大部分內置函數,也是使用叠代器協議訪問對象的。例如, sum函數是Python的內置函數,該函數使用叠代器協議訪問對象,而生成器實現了叠代器協議,所以,我們可以直接這樣計算一系列值的和:

sum(x ** 2 for x in xrange(4))

而不用多此一舉的先構造一個列表:

sum([x ** 2 for x in xrange(4)]) 

計算機基礎-----叠代器 和生成器