专栏首页python3python3基础:生成器

python3基础:生成器

前言

在python中,边循环边计算的机制就称为生成器(generator)。使用生成器当用到数据的时候在生成,这样可以节约空间,提高效率。生成器是一种特殊类型的迭代器,所以也会有__init__()和__next__()两个方法:

__iter__方法负责返回一个迭代器(在迭代器中返回自己,在可迭代对象中返回帮助自己迭代的迭代器)

_next__方法:当前要获取的元素没有越界,就返回当前元素,然后自己指向为下一个元素等待返回;如果上次反回了最后一个元素,这一次再调用next的时候已经没有元素了,就抛出StopIteration异常。

两种实现方式

1.( ) 括号内 放入列表推倒表达式 返回一个生成器对象

  • 用next()方法取出元素:
myIterator = ( x*2 for x in range(5))
print(type(myIterator))

print(next(myIterator))
print(next(myIterator))
print(next(myIterator))
print(next(myIterator))
print(next(myIterator))
print(next(myIterator))#报错,因为没有元素可以取了

执行结果:

说明:

 写法和推导列表非常相似,只是由[]换成了()。由于生成器也是迭代器,所以可以使用next()方法将元素一个一个取出来,当所有的元素都取出后再调用next()方法就会抛出StopIteration异常。

  • 利用for循环取出元素:
myIterator = ( x*2 for x in range(11))
print(type(myIterator))
for i in myIterator:
    print(i,end=" ")

执行结果: 

说明:

由于生成器也是迭代器所以可以放在for循环中操作,将元素一个一个取出来。可以发现使用这种方法不会有异常抛出,因为for循环内部已经处理了。

2.yield关键字

比如我们定义一个函数,打印生成n以内的整数,代码如下:

def my_print(n):
      for i in range(n):
            print(i)

my_print(5)

 执行结果:

当把print换成yield之后,这个函数就是一个生成器了,代码如下:

def my_print(n):
      for i in range(n):
            yield(i)

print(my_print(5))
for i in my_print(5):
      print(i)

执行结果:

说明:

只是由print改成了yield就得到了一个生成器对象,可以用next()或者for循环将数据取出来。换成yield之后到底发生了什么?

当函数执行到yield i 的时候,函数会把i的数值抛出来,我们用for循环遍历的时候获取了yield 后面的值,然后函数就会暂停,等待下一次遍历的时候,函数从yield继续向下执行,直到遇到yield的时候又返回了i的值,然后函数再暂停,等待下一次唤醒。这个循环一直做,到函数结束的时候。

两个练习

1.用生成器生成杨辉三角

def triangles(n):
      temp_list= [1]
      for i in range(1,n+1):
            yield temp_list
            #每一行是一个list,由上一次计算的结果中每相邻的两个元素之后作为新列表的中间值
            temp_list = [temp_list[i]+temp_list[i+1] for i in range(len(temp_list)-1)]
            #第一个位置中添加1
            temp_list.insert(0,1)
            #最后一个位置中添加1
            temp_list.append(1)

for i in triangles(10):
      print(i)

2.以下代码的执行结果是什么?

def add(n, i):
      return n+i

def test():
      for i in range(4):
            yield i

g = test()
for n in [1,10,5]:
      g = (add(n,i) for i in g)

print(list(g))

分析:

g只是代表一个生成器对象,没有for,next,list,tuple调用它的时候它是不会执行的,真实的代码执行逻辑如下:

第1次:n = 1, 执行g=(add(n,i) for i in test())    第2次:n = 10,执行g=(add(n,i) for i in (add(n,i) for i in test())) )   第3次:n = 5,执行g=(add(5,i) for i in (add(n,i) for i in (add(n,i) for i in test())) )) 到第3次的时候n的值就是5,也就是说前两次给n赋的值会覆盖掉,或者可以这样理解,上面的代码等价于:

def add(a,b):            
    return a + b
def test():              
    for r in range(4):
        yield r
g=test()
n=2
g=(add(n,i) for i in g)
n=10  #覆盖前面n的值
g=(add(n,i) for i in g)
n=5  #覆盖前面n的值
g=(add(n,i) for i in g)
print(list(g))

 g因为前面做过定义,每次需要把之前定义的带入,所以当n=5 的时候,g=(add(5,i) for i in (add(n,i) for i in (add(n,i) for i in test())) )),最终的执行结果是[15, 16, 17, 18]

总结

1.碰到for循环套生成器,就拆开来做 ;

2.生成器和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而生成器函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行

参考链接:

https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014317799226173f45ce40636141b6abc8424e12b5fb27000

https://www.cnblogs.com/gkx0731/p/9538348.html

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • [PYTHON] 核心编程笔记之八-Py

    if make_hard_copy: send_data_to_printer()

    py3study
  • python 高级特性:List Comprehensions

    #common establish way lis1 = []; for x in range(1, 10):     lis1.append(x); prin...

    py3study
  • Python学习笔记整理(十一)pyth

    while语句,提供了编写通用循环的一种方法,而for语句是用来遍历序列对象内的元素,并对每个元素运行一个代码块。break,continue用在循环内,跳出整...

    py3study
  • [PYTHON] 核心编程笔记之八-Py

    if make_hard_copy: send_data_to_printer()

    py3study
  • Python学习笔记整理(十一)pyth

    while语句,提供了编写通用循环的一种方法,而for语句是用来遍历序列对象内的元素,并对每个元素运行一个代码块。break,continue用在循环内,跳出整...

    py3study
  • python 高级特性:List Comprehensions

    #common establish way lis1 = []; for x in range(1, 10):     lis1.append(x); prin...

    py3study
  • Swift编程小技巧

    Swift中有很多有用的小技巧,用好了能使代码更加安全,简洁,易于理解或效率更加高效,在这记录一些编写swifty code的小技巧。

    韦弦zhy
  • python for循环

    当range执行完之后,代码执行else部分代码。如果遇到break,终止循环,不会走else代码

    py3study
  • Python练手例子(4)

    16、一个数如果恰好等于它的因子之和,这个数就称为"完数"。例如6=1+2+3.编程找出1000以内的所有完数。

    py3study
  • 学习笔记-小甲鱼Python3学习第九讲

    >>> fruits = ['apple','橘子','banana','哈密瓜','pear']           #水果列表frutis

    py3study

扫码关注云+社区

领取腾讯云代金券