初识python迭代和生成器

接触python迭代器,生成器后,查阅资料整理了一些知识点,写了一些自己的感悟,如有错误希望及时指正。

  • 有一个列表,依次读取其中的值,就是迭代的意思,当一个对象是可以迭代的,可以使用for in 对其进行迭代。
    list = [1, 2, 3]
    for i in mylist:
        print(i)
    #result:
         1
         2
         3

    from collections import Iterable
    print(isinstance([1, 2, 3], Iterable))      #true
    print(isinstance({}, Iterable))                #true
    print(isinstance(123, Iterable))            #false
    print(isinstance('abc', Iterable))            #true

    from collections import Iterator
    print(isinstance([1, 2, 3], Iterator))        #false
    print(isinstance({}, Iterator))                #false
    print(isinstance(123, Iterator))            #false
    print(isinstance('abc', Iterator))            #false

可以看出list、dict和str都是可迭代的。但是他们并不是迭代器。

  • 可以被next()函数调用并不不断返回下一个值得对象称为迭代器:Iterator,迭代器有一个特性,惰性计算。惰性计算指的是在调用时才会计算值,它可以避免不必要的计算,带来性能的提,并且能够节省内存空间。在下面生成器的例子中,更加具体的介绍了这一个特性。
    生成器是可以迭代的,但是你只可以读取它一次 ,因为它并不把所有的值放在内存中,它是实时地生成数据;
    下面的代码中,生成器表达式和列表解析语法相似,只不过把列表解析的[]换成()。生成器表达式能够做的事情,列表解析很多也是能够胜任的,但是相较于较大的数据序列时,生成器的优势就能够体现出来,列表解析就会占用较大内存。在下面代码的第一行我们定义了一个g_generator,打印出来的类型显示是生成器,在定义时,系统并不会对其分配内存,在下面for in 循环时,才会真正的开始计算。
    g_generator = (x * x for x in range(10))
	print(type(g_generator))						#<class 'generator'>
	print(isinstance(g_generator, Iterable))		#true
	print(isinstance(g_generator, Iterator))		#true
	for i in g_generator:
	    print(i)									
    	#0
    	#1
    	#4
    	#9
    	#16
    	#25
    	#36
    	#49
    	#64
    	#81						

在生成器中存在着next()和iter()方法,通过help(g_generator)来查看:

        <genexpr> = class generator(object)
	 |  Methods defined here:
	 |  
	 |  __del__(...)
	 |  
	 |  __getattribute__(self, name, /)
	 |      Return getattr(self, name).
	 |  
	 |  __iter__(self, /)
	 |      Implement iter(self).
	 |  
	 |  __next__(self, /)
	 |      Implement next(self).
	 |  
	 |  __repr__(self, /)
	 |      Return repr(self).
	 |  
	 |  close(...)
	 |      close() -> raise GeneratorExit inside generator.
	 |  
	 |  send(...)
	 |      send(arg) -> send 'arg' into generator,
	 |      return next yielded value or raise StopIteration.
	 |  
	 |  throw(...)
	 |      throw(typ[,val[,tb]]) -> raise exception in generator,
	 |      return next yielded value or raise StopIteration.
	 |  

通过for in 循环和generator的next()方法,可以很容易的取想要得数,虽然上面g_generator有10个数,但是通过next()打印需要的5个数,后面的5个就没有被计算,极大的节省了内存。

    for i in range(5):
		print(next(g_generator))
		#0
    	#1
    	#4
    	#9
    	#16

迭代是一个实现可迭代对象(实现 __iter__() 方法)和迭代器(实现 __next__() 方法)的过程。可迭代对象是你可以从其获取到一个迭代器的任一对象。迭代器是那些允许你迭代可迭代对象的对象。

  • yield关键字,类似于return,作用是把一个函数变成一个 generator。下面通过举例Fibonacci数列来形象地解释。首先定义一个fib函数,python解释器会将函数中yield b 视作generator,我们通过打印fib()的类型来证明。调用fib(6)时,fib()函数并不会执行,而是返回了一个可迭代对象。在for循环执行时,才会执行。通过debug可以发现,每次循环都会执行 fib 函数内部的代码,执行到 yield b 时,fib 函数就返回一个迭代值,下次迭代时,代码从 yield b 的下一条语句继续执行,直到再次遇到 yield。同样我们可以调用next()方法来执行,3.X版本方法变为__next__()
    def fib(x):
    n, a, b = 0, 0, 1
    while n < x:
        yield b
        a, b = b, a + b
        n += 1 
  

	f = fib(6)
	print(f)				#<generator object fib at 0x000001B78B95BDB0>
	print(type(f))			#<class 'generator'>
	print(isinstance(f, Iterable))	#true
	print(isinstance(f, Iterator))	#true
	for i in f:
	    print(i)
	#1
	#1
	#2
	#3
	#5
	#8
	ff = fib(6)
	print(ff.__next__())		#1
	print(ff.__next__())		#1
	print(ff.__next__())		#2

参考内容:https://stackoverflow.com/questions/231767/what-does-the-yield-keyword-do

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值