本文参考 景霄大神的《python核心技术与实战》python
一 、python中的容器、可迭代对象、迭代器的使用
容器: python中一切皆对象, 对象的抽象就是类, 而对象的集就是容器,因此列表, 元祖,字典等都是容器,而且全部的容器都是能够迭代的(iterable)
迭代器: 迭代器(iterator)提供了next的方法, 调用这个方法会获得迭代器的下一个对象,直到取完抛出StopIteration错误类型,因此能够经过可迭代对象调取next方法完成遍历迭代器。
能够经过isinstance校验是否为可迭代对象isinstanstance(obj, lterable)
二 、生成器
通俗的解释是懒人的迭代器, 在使用迭代器构成中全部的元素都会直接一次保存在内存中,可是生成器全部的元素经过调取next动态生成, 直观的感觉就是节省了不少资源
举例:生成一亿的迭代器[for i in range(10000000000)],可是在实际运用中并不会使用到每一个元素, 这个时候用生成器替代迭代器会更高效,也并不会报OOM异常, 生成器写法 ( for i in range(100000000))
做用:迭代器和生成器二者区别还不止内存消耗,迭代器是有穷的,可是由于生成器是动态生成元素,理论上它是能够无限生成下一个元素的,
实例1 计算 (1 + 2 + 3 + ... + n)
def generator(k):
i = 1
while True:
yield i ** k
i = i + 1
gen = gennerator(1)
def get_sum(n):
sum = 0
for i in range(n):
_next = next(gen)
print(_next)
复制代码
就跟这个公式同样, n能够取无穷, 一样理论上生成器也能够取无穷, 上述代码用yield暂停了函数,而且跳转到next()函数, i ** k 即为next返回值, yield的用法还有不少, 能够代替线程用协程的方法完成函数块的切换,省去了线程间切换消耗的资源,能够用send激活, 这边讲了其中一种用法, 一样它也就是用next激活了生成器。
实例2 在列表中查找某个数字的位置
def func1(list, k):
out_list = []
for i, num in enumerate(list):
if num == k:
print('fonud it ', i)
def func2(list, k):
for i, num in enumerate(list):
if num == k:
yield i
复制代码
ps: func2就是生成了一个迭代器对象, 再转list就能够了, 可让代码更加有可读性。markdown
实例3 查找列表中是否包含子列表
def is_instance(check_list, list):
list = iter(list)
return all( i in list for i in check_list) # all()函数必须全部返回均为True才会返回True
复制代码
3、总结
- 容器是可迭代对象, 可迭代对象调用iter()函数能够获得一个迭代器, 迭代器经过next()获得下一个元素, 从而支持遍历, 注意点: 迭代器遍历只可使用一次,缘由是由于迭代器会存到缓冲区内, 经过移动指针来消耗缓冲区, 随时读取,可是读过一次以后指针就在缓冲区的末尾, 因此不可重复读取。
- 生成器是一种特殊的迭代器,合理使用生成器能够下降内存占用,优化程序结构,提升程序运行速度。
- 生成器也是在python2中协程的一种重要的实现方式(在python中因为GIL的存在每每使用多进程+协程的方式实现并发), 而在python3.5以上引用了async await语法糖