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

 

介绍

可迭代的:内部实现了__iter__方法

迭代器:内部实现了__iter__,__next__方法

生成器:yield,yield from

 

使用

__iter__()

__next__()

__length_hint__()            # 长度

都可以使用for循环

只有迭代器可以使用next()

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__

# 判断内部是不是实现了__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和Iterator

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语句一次返回一个结果。生成器的好处,就是一下子不会在内存中生成太多的数据

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一下进行初始化(如上面的例子),通过装饰器完成此步骤

让装饰器去激活
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

posted @ 2018-08-20 10:48  fat39  阅读(136)  评论(0编辑  收藏  举报