生成器

之前学过列表生成式,但是如果仔细考虑它的缺点是浪费内存空间
那么有什么另外好的办法吗,下面来看看生成器的内容
一、 生成器的两种方式:
1. x = (x for x in range(10)) 是不是跟列表生成式很像,[ ] 和 ()
2. yield
1.第一种方式

x = (x for x in range(5))
# print(type(x))  # 
# print(next(x))  # 0
# print(next(x))  # 1
# print(next(x))  # 2
# print(next(x))  # 3
# print(next(x))  # 4
# print(next(x))  # 报错StopIteration

# 利用for循环取数 生成器都可以迭代)(Iterable)
for i in x:
    print(i)

思考:从这里看生成器比起列表生成式有什么优点吗?
其实这里的for循环主要有2步,1是取x的next值,2是碰到最后一个值不会抛出异常信息。这种生成器的方式 是每次把生成的值给到i,依次赋值,这样的方式极大的节省了内存空间,如果是列表,那么每个值都占了内存,而生成器这样的方式可以自动回收掉。

2.第二种方式

def f():
   yield 1

g = f()
print(type(g)) #
#这里的yield 既是返回值关键字,又是生成器的next的标记,来看下面的例子
def f():
    print('come1')
    yield 1
    print('come2')
    yield 2


g = f()
print(next(g))
print(next(g))
print(next(g))

输出结果:

come1
1
come2
2
Traceback (most recent call last):
  File "D:/workspace/python3.6/testing/day1/生成器.py", line 30, in 
    print(next(g))
StopIteration

从上面可以看出,每次next都是以yield为标记,并且可以返回值,下一次循环从上一个yield开始,直到最后一次再执行的话会报StopIteration的错误。

那么再来思考一个问题,for i in 后面加的是什么?是生成器吗?迭代器吗?看下面的例子可以举一反三:

a = [1, 2, 3]
for i in a:
    print(i)

很显然字符串a肯定不是什么器,它是可迭代对象!那么生成器就是可迭代对象。那么具体可迭代对象的概念是什么呢,内部有iter()的方法就是可迭代对象。

生成器的调用有两种方法,刚才试过了next,其实还有一种

叫send方法,该方法的特点是可以传递值

def foo():
    print('come1')
    count = yield 1
    print(count)
    yield 2


a = foo()         #生成器
b = a.send(None)  #等同于next(a) 第一次传递如果没有next,那么只能传递None
print(a)          #1
c = a.send('eeeee')
print(c)     #2

从上面可以看出来第一次yield 1直接返回了,第二次执行回到yield 1 然后把传递的值给了count。

你可能感兴趣的:(生成器)