1 2 3 4

【python之路29】python生成器generator与迭代器

 

补充:2020年3月1日

一、迭代器--补充

li = [11,22,33]
bol = "__iter__" in dir(li)
print(bol) #如果__iter__list功能里面表示li是可迭代的

#li是可迭代的,但li不是迭代器
it = li.__iter__()
print(it) #<list_iterator object at 0x0000026F5CFFEA58>,则it是个迭代器
#print(it.__next__()) #迭代器可以用it.__next__()一个一个的按顺序取值

#迭代器的内部取值原理
while True:
try:
print(it.__next__())
except StopIteration:
break

#总结:可迭代的对象不一定是迭代器,例如list,单迭代器一定是可迭代的

 二、生成器---补充

生成器,可以取迭代循环,实质上生成器是迭代器

send(1) 的用法与__next__()用法基本一样,唯一的区别是,先发送一个值给上一个yield然后再向下执行:

def func():
    print('11')
    aa = yield 1
    print(aa)
    print('22')
    bb = yield 2
    print(bb)
    print('33')
    yield 3


gen = func()  # 运行后gen是生成器
gen.__next__()
gen.send("aa")
gen.send("bb")
# 运行结果:
# 11
# aa
# 22
# bb
# 33

 

一、python生成器

 python生成器原理:

只要函数中存在yield,则函数就变为生成器函数

#!usr/bin/env python
# -*- coding:utf-8 -*-

def xrange():
    print('11')
    yield 1
    print('22')
    yield 2
    print('33')
    yield 3

r = xrange()  #不执行,产生一个生成器,注意xrange不是生成器,r才是生成器
print(r)  #<generator object f1 at 0x0000017D4A1D1CA8>

re = r.__next__()
print(re) #打印输出11 1,生成器执行完yield后暂停执行,当再次执行__next__()时,从上一个yield后面继续执行
re = r.__next__()
print(re) #打印输出11 1
re = r.__next__()
print(re) #打印输出11 1

 python2.7中xrange的原理

#!usr/bin/env python
# -*- coding:utf-8 -*-
def xxrange(n):
    num = 0
    while True:
        if num == 5:
            return
        yield num
        num += 1

r = xxrange(5)
re1 = r.__next__()
re2 = r.__next__()
re3 = r.__next__()
re4 = r.__next__()
re5 = r.__next__()
print(re1,re2,re3,re4,re5)  #打印0 1 2 3 4

 2.7版本xrange完全实现:

#!/ufr/bin/env python
# -*- coding:utf-8 -*-

def xxrange(n1,n2=None):
    if n2 is None:
        n = 0
        while n < n1:
            yield n
            n = n + 1
    else:
        n = n1
        while n1 <= n < n2:
            yield n
            n = n + 1


#bb = xxrange(5)
for i in xxrange(1,5):
    print(i)

 

1、迭代器

迭代器是访问集合元素的一种方式。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代途中往后退。另外,迭代器的一大优点是不要求事先准备好整个迭代过程中所有的元素。迭代器仅仅在迭代到某个元素时才计算该元素,而在这之前或之后,元素可以不存在或者被销毁。这个特点使得它特别适合用于遍历一些巨大的或是无限的集合,比如几个G的文件

特点:

  1. 访问者不需要关心迭代器内部的结构,仅需通过next()方法不断去取下一个内容
  2. 不能随机访问集合中的某个值 ,只能从头到尾依次访问
  3. 访问到一半时不能往回退
  4. 便于循环比较大的数据集合,节省内存
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
>>> a = iter([1,2,3,4,5])
>>> a
<list_iterator object at 0x101402630>
>>> a.__next__()
1
>>> a.__next__()
2
>>> a.__next__()
3
>>> a.__next__()
4
>>> a.__next__()
5
>>> a.__next__()
Traceback (most recent call last):
  File "<stdin>", line 1in <module>
StopIteration

2、生成器

一个函数调用时返回一个迭代器,那这个函数就叫做生成器(generator);如果函数中包含yield语法,那这个函数就会变成生成器;

1
2
3
4
5
def func():
    yield 1
    yield 2
    yield 3
    yield 4

上述代码中:func是函数称为生成器,当执行此函数func()时会得到一个迭代器。

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> temp = func()
>>> temp.__next__()
1
>>> temp.__next__()
2
>>> temp.__next__()
3
>>> temp.__next__()
4
>>> temp.__next__()
Traceback (most recent call last):
  File "<stdin>", line 1in <module>
StopIteration

3、实例

a、利用生成器自定义range

1
2
3
4
5
6
7
8
def nrange(num):
    temp = -1
    while True:
        temp = temp + 1
        if temp >= num:
            return
        else:
            yield temp

b、利用迭代器访问range

1
...
posted @ 2017-03-03 15:25  I我的博客I  阅读(260)  评论(0编辑  收藏  举报