目录

Python生成器学习笔记

一、前言

  • 生成器与迭代器可以说是python中比较强大的两个特性。
  • 相对于迭代器,生成器则要强大、高级一些。
  • 生成器用好了,你的代码将会变得非常的优雅。
  • OK,在学习生成器之前,我们先通过demo来看生成器是如何创建的以及如何使用它

二、生成器的创建及使用

  • 其实,创建生成器就像创建函数一样简单。

  • demo如下:

  • 首先我们声明一个列表,我们要做的是把列表内的元素按从左到右依次输出

      nested = [[1,2],[3,4,5],[6]]
    
  • 我们通过创建一个函数来完成

      def flatten(nested):
      	for sublist in nested:
      		for element in sublist:
      			yield element;
    
  • 调用如下:

      nested = [[1,2],[3,4,5],[6]]
      for num in flatten(nested=nested):
      	print(num);
    
  • 输出如下:

      1
      2
      3
      4
      5
      6
    
  • 如果你想通过一个类似上面的列表来创建一个单列表,我们也可以这样子做

      lst1 = list(flatten(nested))
    
  • 我们来打印下lst1的元素

      print(lst1) : [1, 2, 3, 4, 5, 6]
    
  • 代码是死的,人是活的,对于一个需求,我们有不同的方法去处理,当然,加入我们刚接触编程,经验不多,用的方法可能就比较笨,但技术是个积累的过程,1w小时理论同样适用。

  • ok,我们前面创建的生成器比较死板,我们是根据列表才编写的,里面只处理来两层嵌套,假如我的数据是多层嵌套的,那就不适用了。

  • 这时你可能会说,那你再改改不就可以了么?

  • 咱是要写优雅的代码的人,怎么能这么敷衍了事呢。

  • Ok,我们再对上面的函数改改把!

      def flatten(nested):
      	try:
      		for sublist in nested:
      			for element in flatten(sublist):
      				yield element;
      	except TypeError:
      		yield nested;
    
  • 调用如下:

      nested = [[1,2],[3,4,[5,[6,7]]],[8]]
      for num in flatten(nested=nested):
      	print(num);
    
  • 输出:

      1
      2
      3
      4
      5
      6
      7
      8
    
  • 修改解说: 1、首先我们方法借助了递归。 2、其会一直调用递归,当调用flatten函数时传入的不是列表了,就会报TypeError错误,然后yield 该元素,yield你可以暂时看成return来理解。然后for in 里的element就是返回的元素,进而递归结束,这样子理解还是晕晕的其实,后面我们会单独一篇文章来讲解yield。

  • Ok,其实上面的函数有个bug,如果列表的元素是一个字符串,那么会发生什么问题呢?没错,当时会报错,因为我们的字符串是不能使用for in的。我们再稍微修改一下下。

  • flatten加强版!

      def flatten(nested):
      	try:
      		try:nested+''
        except TypeError:
      			pass;
      		else: raise TypeError('element can not be string');
      		for sublist in nested:
      			for element in flatten(sublist):
      				yield element;
      	except TypeError as e:
      		yield nested;
    
  • 在遍历前对其进行一个+操作,如果其nested+‘‘没有报错,说明其是字符串,然后我们执行raise 触发一个TypeError异常,让其直接调用下面的yield nested返回,不再进行for in 及递归调用。

  • 现在你可以愉快的在列表中加入字符串元素来。

  • 调用如下:

      nested = [['hello',2],[3,4,[5,[6,7]]],[8]]
      for num in flatten(nested=nested):
      	print(num);
    
  • 输出如下:

      hello
      2
      3
      4
      5
      6
      7
      8
    
  • 小结:生成器就是一个包含yield关键字的函数。当函数被调用时,在函数体中的代码不会被马上执行,而会返回一个迭代器。每次请求一个值,就会执行生成器中的代码,直到遇到一个yield或者return语句。

  • yield语句表示应该生成一个值。

  • return语句表示生成器要停止执行。return语句只有在一个生成器中使用时才能进行无参数调用。

  • 生成器是由两部分组成

1、生成器函数:用def 语句定义的包含yield部分 2、生成器迭代器 : 函数的返回部分

  • 本次我们就先简单的学习生成器的创建和使用。
  • 小伙伴们有什么好的建议都可以给我留言哦!