迭代器,生成器

Posted lara0520

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了迭代器,生成器相关的知识,希望对你有一定的参考价值。


一、什么是可迭代对象?

方法一、dir(被测对象),如果他含有__iter__,那这个对象就叫做可迭代对象
 s = "abc"
 print("__iter__" in dir(s))        #True
 print("__iter__" in dir(333))      #False

遵循可迭代协议

    1.可迭代协议:可以被迭代要满足要求的就叫做可迭代协议。内部实现了__iter__方法

  iterable:可迭代的------对应的标志

  什么叫迭代?:一个一个取值,就像for循环一样取值

       字符串,列表,元组,集合,字典都是可迭代的

    2、迭代器协议:内部实现了__iter__,__next__方法

  迭代器大部分都是在python的内部去使用的,我们直接拿来用就行了

  迭代器的优点:如果用了迭代器,节约内存,方便操作

   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])))
  iter_list=[1,2,3,4,5,6].__iter__()

  print(iter_list.__length_hint__())#获取迭代器中元素的长度
  print(iter_list.__setstate__(4))#根据索引指定从哪里开始迭代
 
  print(iter_list.__next__())
  print(iter_list.__next__())
  print(iter_list.__next__())#一个一个的取值
  print(next(iter_l))
  next(iter_list)这个方法和iter_list.__next__()方法一样,
  推荐用next(iter_list)这个

方法二、测试是迭代器还是可迭代对象

type 只能判断数据类型

例子1
l = [1,2,3]
l_iter = l.__iter__()

from collections import Iterable
from collections import Iterator

print(isinstance(l,Iterable)) #True #判断他是可迭代对象
print(isinstance(l,Iterator)) #False #判断他是迭代器
print(isinstance(l_iter,Iterator)) #True
print(isinstance(l,list)) #True

例子:range 是可迭代对象还是迭代器

技术分享图片
i = range(10)
# print( "__iter__" in  dir(range(10)))     #True
# print("__next__" in dir(range(10)))       #False

from collections import Iterable
from collections import Iterator
print(isinstance(i,Iterable))      #判断他是可迭代对象
print(isinstance(i,Iterator))      #判断他是迭代器
range例子

二、可迭代对象 iterable 与 迭代器 iterator 有什么关系


可迭代对象---> 转换成迭代器
可迭代对象__iter__() --->迭代器

s = "abc"
s1 = s.__iter__()
print(s1)   #<str_iterator object at 0x00000228E73F7278> 遵循得带协议
 li1 = [1,2,3,5]
 print("__iter__" in dir(list))           #True
 
 li2 = li1.__iter__()
 print("__next__" in dir(li2))           #True

 print(list2.__next__())
 print(list2.__next__())
 print(list2.__next__())
 print(list2.__next__())

三、迭代器取值

只含有__iter__方法的数据是可迭代对象
含有__iter__方法,并且含有__next__方法的数据是迭代器

技术分享图片
s2 = "abc"
s3 = s2.__iter__()   #<str_iterator object at 0x00000128D84A7828>
#
# print(s3.__next__())
# print(s3.__next__())
# print(s3.__next__())
print("__iter__" in dir(s2))   #True
print("__next__" in dir(s2))   #False
print("__iter__" in dir(s3))   #True
print("__next__" in dir(s3))   #True
例子1
技术分享图片
l = [1,2,3,4,5]
print("__iter__" in dir(l))    #True
print("__next__" in dir(l))    #False

l2 = l.__iter__()
print(l2.__next__)
print(l2.__next__)
print(l2.__next__)
print(l2.__next__)
print(l2.__next__)
例子2

四、迭代器的意义

1.迭代器节省内存
2.迭代器惰性机制
3,迭代器不能反复,一直向下执行.


五、for循环的机制.

内部含有__iter__方法,他会将可迭代对象先转化成迭代器,
然后在调用__next__方法.
他有异常处理的方法.

用while 循环模拟 for 循环机制

 li = [1,2,3]
 li_iter = li.__iter__()
 while True:
     try:                           #遇到错误,try一下
         print(li_iter.__next__())
     except StopIteration:
         break
     有异常处理能力

总结:
可迭代对象:str list tuple dict set range
迭代器: 文件句柄,map


六、生成器

(一)生成器的本质是迭代器,生成器是自己用python写的迭代器
1,可以用生成器函数
2,可以用各种推导式构建迭代器.
3,可以通过数据转化.

(二)

普通函数
例子1.1
def func():
print(111)
return 222
ret = func()
print(ret)

生成器函数,生成器
return yield 区别
return 返回给调用者值,并结束此函数.
yiled 返回给调用者值,并将指针停留着当前位置.
例子1.2
def gener():
    print("aaa")
    yield 222            #yield是表示是生成器函数
    print("bbb")
    yield 333
    print("ccc")
g = gener()              #不是执行函数,是产生生成器
print(g.__next__())      # 一个next,一个yield,并且光标停留在yield后
print(g.__next__())
技术分享图片
例子2.1:
def cloth():
    for i in range(100):
        print(i)
cloth()

例子2.2:
方法一、
def cloth():
    for i in range(1000):
        yield "衣服%s"%i
f = cloth()
print(f.__next__())     #衣服0
print(f.__next__())     #衣服1

方法二、
def cloth():
    for i in range(1000):
        yield "衣服%s"%i
f = cloth()
for i in range(50):
    print(f.__next__())
例子2:range

 

(三)面试题

send
1.send 和 next 功能一样
2.给上一个 yiled 整体 发送一个值
3.获取第一个值的时候,不能用send,只能用next
可以给上一个yiled整体发送一个值
技术分享图片
def gener():
    print("aaa")
    yield 222
    print("bbb")
    count = yield 333
    print("----->",count)
    yield "aaa"
    yield 333
g = gener()
print(g.__next__())
print(g.send(None))
print(g.send("AAAA"))
send例子

 

七、列表推导式

# (一)通过数据转换
# list() tuple() 可以将生成器对象转换
# 生成器 = 生成器对象



#(二)列表推导式和生成器表达式

#[变量(加工后的变量) for 变量 i in 可迭代的数据类型 ] 列表的推导式
#[ 变量(加工后的数据) for 变量i in 可迭代的数据类型 ] 列表的推导式, 循环模式
#[ 变量(加工后的数据) for 变量i in 可迭代的数据类型 if 条件] 列表的推导式, 筛选模式

# li = []
# for i in range(1,11):
# li.append(i)
# print(li)

# li = []
# for i in range(1,11):
# li.append("python%s期"%i)
# print(li)

# li1 = [i for i in range(10)]
# print(li1)

# li2 = ["python%s期"%i for i in range(1,11)]
# print(li2)

#(三)列表推导式,生成器表达式的作用

#1,列表推导式比较直观,占内存
#2,生成器表达式不容易看出内容,省内存.
# 3.python不但使用迭代器协议,
# 让for循环变得更加通用。大部分内置函数,也是使用迭代器协议访问对象的。

# 例如sum 函数是python的内置函数。
# sum(x**2 for x in range(4))

# 30以内能被3整除的数
# li = [i for i in range(31) if i%3 == 0]
# print(li)
#
# # 30以内能被3整除的数的平方
# li1 = [i**2 for i in range(31) if i%3 == 0 ]
# print(li1)


# 例子1.将一个字典的key 和 value 对调
# 前提是value是不可变数据类型,因为键是不可变数据类型
# 例子1:
# mcase = {"a" : 10 ,"b" : 34}
# mcasw_frequency = {mcase[k]:k for k in mcase}
# print(mcasw_frequency)

# 例子2
# names = [[‘Tom‘, ‘Billy‘, ‘Jefferson‘, ‘Andrew‘, ‘Wesley‘, ‘Steven‘, ‘Joe‘],
# [‘Alice‘, ‘Jill‘, ‘Ana‘, ‘Wendy‘, ‘Jennifer‘, ‘Sherry‘, ‘Eva‘]]
#
# f = [a for i in names for a in i if a.count("e") == 2]
# print(f)

























































































































































以上是关于迭代器,生成器的主要内容,如果未能解决你的问题,请参考以下文章

python:可迭代对象,迭代器,生成器函数,生成器的解析举例代码说明

python:可迭代对象,迭代器,生成器函数,生成器的解析举例代码说明

10.迭代器/生成器/协程函数/列表生成器

Interator和Generator

Interator和Generator

Interator和Generator