Python基礎_可迭代的/迭代器/生成器

 

介紹

可迭代的:內部實現了__iter__方法html

迭代器:內部實現了__iter__,__next__方法app

生成器:yield,yield fromide

 

使用

__iter__()

__next__()

__length_hint__()            # 長度

均可以使用for循環函數

只有迭代器能夠使用next()spa

l = [1,2,3,4]
l1 = [1,2,3,4].__iter__()

for item in l:print(item)
# 1
# 2
# 3
# 4
for item in l1:print(item)
# 1
# 2
# 3
# 4

l = [1,2,3,4]
l1 = [1,2,3,4].__iter__()
print(next(l1))  # 1
print(next(l1))  # 2
print(l1.__next__())  # 3

print(next(l))  # 報錯
均可以for循環,只有迭代器能夠使用next()

 

判斷迭代器和可迭代的方法

內部實現__iter__、__next__3d

# 判斷內部是否是實現了__iter__和__next__方法
l = [1,2,3,4]
l1 = [1,2,3,4].__iter__()  # 使用__iter__方法使其變成迭代器,可實現next()或__next__()方法

print("__iter__" in dir(l))  # True,可迭代的
print("__next__" in dir(l))  # False,非迭代器
print("__iter__" in dir(l1))  # True,可迭代的
print("__next__" in dir(l1))  # True,迭代器
內部實現__iter__、__next__

Iterable和Iteratorcode

from collections import Iterable  
from collections import Iterator

l = [1,2,3,4]
print(isinstance(l,Iterable))  #isinstance判斷類型的  # True
print(isinstance(l,Iterator))  # False
Iterable和Iterator

 

生成器

常規定義函數,可是,使用yield語句而不是return語句返回結果。yield語句一次返回一個結果。生成器的好處,就是一會兒不會在內存中生成太多的數據htm

yield

def  func(): #這是一個簡單的函數
        a=1
        return a
print(func())


def func():
    print('aaaaaaaaaaa')
    a = 1
    yield a  # 返回第一個值
    print('bbbbbb')
    yield 12  # 返回第二個值


ret = func()  # 得拿到一個生成器
# print(ret)#返回的是一個地址
print(next(ret))#取第一個值
print(next(ret))# 取第二個值
print(next(ret))# 取第三個值,會報錯,由於沒有yield第三個值
簡單的生成器,yield
必須先用next再用send
def average():
    total=0 #總數
    day=0 #天數
    average=0 #平均數
    while True:
        day_num = yield average   #average=0,經過外部的send,把數據傳給day_num,同時把average出去做爲返回值。
        total += day_num
        day += 1
        average = total/day
avg=average() #直接返回生成器
next(avg)#激活生成器,avg.send(),什麼都不傳的時候send和next的效果同樣
print(avg.send(10))
print(avg.send(20))#send   1.傳值 2.next
print(avg.send(30))
計算移動平均值
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)
生成器監聽文件例子

因爲需實現send的生成器須要先next一下進行初始化(如上面的例子),經過裝飾器完成此步驟blog

讓裝飾器去激活
def wrapper(func):
    def inner(*args,**kwargs):
       ret = func(*args,**kwargs)
       next(ret)
       return ret
    return inner

@wrapper
def average():
    total=0 #總數
    day=0 #天數
    average=0 #平均數
    while True:
        day_num = yield average   #average=0
        total += day_num
        day += 1
        average = total/day


ret=average() #直接返回生成器
print(ret.send(10))
print(ret.send(20))#send   1.傳一個值過去 2.讓當前yield繼續執行
print(ret.send(30))
帶裝飾器的計算移動平均值

yield from

def func():
    # for i in 'AB':
    #     yield i
    yield from 'AB'     yield from 'AB'就至關於上面的for循環,吧循環簡化了
    yield from [1,2,3]

g=func()
print(list(g))
# print(next(g))
# print(next(g))
yield from,至關於for 。。。yield

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

# ======一層循環======
l = [i*i for i in range(1,10)]
print(l)
# 上面的列表推倒式就至關於下面的
l  = []
for i in range(1,10):
    l.append(i*i)
print(l)
l = []


# ======多層循環========
# 1.列表推倒式
l = [i*j for i in range(1,10) for j in range(1,10)]
print(l)
# 2.循環
l = []
for i in range(1,10):
    for j in range(1,10):
        s = i*j
        l.append(s)
print(l)
列表推導式 []
l=[{'name':'v1','age':'22'},{'name':'v2'}]

name_list=(dic['name'] for dic in l)#吧列表生成器的[]改爲()
print(name_list)#取出的是一個生成器,而不是要取得值,因此得加上next
print(next(name_list))
print(next(name_list))
# print(next(name_list))
生成器表達 () 其實是把列表推導式的[]改成()

 

參考or轉發

http://www.cnblogs.com/haiyan123/p/7275045.html內存

相關文章
相關標籤/搜索