python全棧闖關--13-迭代器和生成器

 一、迭代器

可迭代協議

  含有雙下劃線方法__iter__()方法的都是可迭代函數

迭代器協議

  內部含有__next__和__iter__方法的就是迭代器spa

 

# 判斷是否函數__iter__方法
print("__iter__" in dir(int))
print("__iter__" in dir(bool))
print("__iter__" in dir(list))
print("__iter__" in dir(dict))
print("__iter__" in dir(set))
print("__iter__" in dir(tuple))
print("__iter__" in dir(enumerate([])))
print("__iter__" in dir(range(1)))

 

print([])
print([].__iter__())  # 使用__iter__方法後,返回值爲一個迭代器
print(set(dir([].__iter__())) - set(dir([])))  # {'__setstate__', '__length_hint__', '__next__'}
print([1, 2, 'aas', 'a'].__iter__().__length_hint__())  # 返回元素的個數

# 迭代器使用next方法,能夠遍歷值
l = [1, 2, 3, 4]
iterator = l.__iter__()
print(iterator.__next__())
print(iterator.__next__())
print(iterator.__next__())
print(iterator.__next__())
print(iterator.__next__())  # 迭代器返回值完畢後,程序報錯「StopIteration」

 

Iterable 可迭代的 -- > __iter__  只要含有__iter__方法的都是可迭代的
[].__iter__() 迭代器 -- > __next__  經過next就能夠從迭代器中一個一個的取值code

 

迭代器協議和可迭代協議

  • 能夠被for循環的都是可迭代的
  • 可迭代的內部都有__iter__方法
  • 只要是迭代器,就必定可迭代
  • 可迭代的__iter__()能夠獲得一個迭代器
  • 迭代器中的__next__方法能夠一個一個的獲取值

 

迭代器的好處

  • 從容器中能夠一個一個的取值,能取到全部值
  • 節省空間
    •   迭代器不會所以在內存中開闢一大塊空間,而是隨着循環,每次經過next方法,生成一個值
print(range(100000000000000))
print(list(range(1000000000)))

運行上述代碼,能夠看到,第一個迭代器的時候,很快就返回告終果  range(0, 100000000000000)blog

第二段代碼,機子跑死機了,都沒法正常運行ip

 

二、生成器函數

含有yiled關鍵字的函數都是生成器函數內存

#正常函數
def generaor():
    print('1')
    return 'a'

ret=generaor()
print(ret)

 

 

還有yiled關鍵字時,不能含有return關鍵字get

def generaor():
    print('1')
    yield 'a'  # 替換return關鍵字未yield關鍵字後,就是一個生成器

ret=generaor()
print(ret)

 

 

def generaor():
    print('1')
    yield 'a'  # 替換return關鍵字未yield關鍵字後,就是一個生成器

ret=generaor()
print(ret)
print("next get value:", ret.__next__())  # 生成器使用next函數獲取值

 

 生成器中,使用雙下線方法來獲取返回值generator

 

 

含有多個yield時,每次使用__next__都是到yield時,中止執行,返回值。it

單生成器中的值返回完畢時,報錯StopIterationio

def generaor():
    print('1')
    yield 'a'  # 替換return關鍵字未yield關鍵字後,就是一個生成器
    print('2')
    yield 'b'
    yield 'c'

ret=generaor()
print(ret)
print("next get value:", ret.__next__())  # 生成器使用next函數獲取值
# 1
# next get value: a

print("next get value:", ret.__next__())  # 生成器使用next函數獲取值
# 2
# next get value: b

print("next get value:", ret.__next__())  # 生成器使用next函數獲取值
# next get value: c
#
print("next get value:", ret.__next__())  # 生成器使用next函數獲取值
# 報錯StopIteration,生成器到達最後的值報錯

 

同時定義多個生成器時,多個生成器間並不矛盾,每一個都能獲取各自獨立的值

def bear():
    for i in range(20000):
        yield "bear %s" % i

g = bear()
g2 = bear()

print('生成器函數1:%s' % g.__next__())
print('生成器函數1:%s' % g.__next__())
print('生成器函數2:%s' % g2.__next__())
print('生成器函數2:%s' % g2.__next__())
print('生成器函數1:%s' % g.__next__())

 

總結:

迭代器:

  • 雙下方法:不多直接調用的方法,通常狀況下,經過其餘語法觸發;
  • 可迭代的:可迭代協議,含有__iter__方法('__iter__' in dir(類型))
  •   可迭代的必定能夠被for循環;
  • 迭代器協議:含有__iter__和__next__的方法。
  •   迭代器必定能夠迭代,可迭代的經過__iter__方法能夠獲得一個迭代器
  • 迭代器的特色:
  •   能夠方便的遍歷,且每一個元素之使用一次;
  •   節省內存;

生成器:

生成器的本質是一個迭代器

  • 生成器函數:
  • 含有yield關鍵字的函數就是生成器:
  • 特色
    • 調用函數,並不會當即執行,返回一個生成器
    • 每次調用,使用__next__獲取一個值
    • 直到取完最後一個值,報錯

從生成器中取數的幾個方法:

  •   for
  •   __next__
  •   數據類型強制轉換,暫用內存

 

練習:

def tail(filename):
    with open(filename) as f:
        while True:
            line = f.readline()
            line = line.strip()
            if line:
                yield line

res = tail('file')
for line in res:
    if 'bear' in line:
        print('***', line)

 

def generator():
    for i in range(2000000000):
        yield "hello, bear %s" % i

g = generator()
print(g.__next__())
n = 0
for content in g:
    n += 1
    if n > 50:
        break
    print(content)
相關文章
相關標籤/搜索