码迷,mamicode.com
首页 > 编程语言 > 详细

python基础列表生成式,迭代器

时间:2018-02-22 21:37:57      阅读:173      评论:0      收藏:0      [点我收藏+]

标签:exce   等价   并发   fun   错误   代码   ons   max   span   

1 >>> L = [x * x for x in range(10)]
2 >>> L
3 [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
4 >>> g = (x * x for x in range(10))
5 >>> g
6 <generator object <genexpr> at 0x1022ef630>

列表生成式和生成器generator,可以通过next()函数获得generator的下一个返回值。generator保存的是算法,每次调用next(g),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。

获取迭代器里面的内容正确的方法是通过for循环。并且不会报错。

>>> g = (x * x for x in range(10))
>>> for n in g:
...     print(n)
...
0
1
4
9
16
25
36
49
64
81

generator非常强大。如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,还可以用函数来实现。

比如,著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到:

1, 1, 2, 3, 5, 8, 13, 21, 34, ...

斐波拉契数列用列表生成式写不出来,但是,用函数把它打印出来却很容易:

 1 def fib(max):
 2     n, a, b = 0, 0, 1
 3     while n < max:
 4         print(b)
 5         a, b = b, a + b
 6         n = n + 1
 7     return done
 8 >>> fib(10)
 9 1
10 1
11 2
12 3
13 5
14 8
15 13
16 21
17 34
18 55
19 done

上面的函数和generator仅一步之遥。要把fib函数变成generator,只需要把print(b)改为yield b就可以了,并定义f=fib(6),f就是个生成器。同样的,把函数改成generator后,我们基本上从来不会用next()来获取下一个返回值,而是直接使用for循环来迭代。但是此方法拿不到函数最终的返回值。如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIterationvalue中:

 1 >>> g = fib(6)
 2 >>> while True:
 3 ...     try:
 4 ...         x = next(g)
 5 ...         print(g:, x)
 6 ...     except StopIteration as e:
 7 ...         print(Generator return value:, e.value)
 8 ...         break
 9 ...
10 g: 1
11 g: 1
12 g: 2
13 g: 3
14 g: 5
15 g: 8
16 Generator return value: done

此处需要练习写代码:还可通过yield实现在单线程的情况下实现并发运算的效果:

 1 #_*_coding:utf-8_*_
 2 __author__ = Alex Li
 3 
 4 import time
 5 def consumer(name):
 6     print("%s 准备吃包子啦!" %name)
 7     while True:
 8        baozi = yield
 9 
10        print("包子[%s]来了,被[%s]吃了!" %(baozi,name))
11 
12 
13 def producer(name):
14     c = consumer(A)
15     c2 = consumer(B)
16     c.__next__()
17     c2.__next__()
18     print("老子开始准备做包子啦!")
19     for i in range(10):
20         time.sleep(1)
21         print("做了2个包子!")
22         c.send(i)
23         c2.send(i)
24 
25 producer("alex")

概念部分:

1.直接作用于for循环的数据类型有以下几种:一是集合数据类型,如listtupledictsetstr等;二是是generator,包括生成器和带yield的generator function。

2.Iterable可迭代对象:可以直接作用于for循环的对象。isinstance()判断一个对象是否是Iterable对象

 1 >>> from collections import Iterable
 2 >>> isinstance([], Iterable)
 3 True
 4 >>> isinstance({}, Iterable)
 5 True
 6 >>> isinstance(abc, Iterable)
 7 True
 8 >>> isinstance((x for x in range(10)), Iterable)
 9 True
10 >>> isinstance(100, Iterable)
11 False

 

3.迭代器Iterator*可以被next()函数调用并不断返回下一个值的对象称为迭代器。可以使用isinstance()判断一个对象是否是Iterator对象。

 

 


 

 

 

转换:listdictstrIterable变成Iterator可以使用iter()函数:

1 >>> isinstance(iter([]), Iterator)
2 True
3 >>> isinstance(iter(abc), Iterator)
4 True

小结

凡是可作用于for循环的对象都是Iterable类型;

凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;

集合数据类型如listdictstr等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。

Python的for循环本质上就是通过不断调用next()函数实现的,例如:

 

 

for x in [1, 2, 3, 4, 5]:
    pass


#等价于

# 首先获得Iterator对象:
it = iter([1, 2, 3, 4, 5])
# 循环:
while True:
    try:
        # 获得下一个值:
        x = next(it)
    except StopIteration:
        # 遇到StopIteration就退出循环
        break

 

python基础列表生成式,迭代器

标签:exce   等价   并发   fun   错误   代码   ons   max   span   

原文地址:https://www.cnblogs.com/letgo-doo/p/8459912.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!