python3迭代器和生成器
1、手动访问迭代器中的元素
#要手动访问迭代器中的元素,可以使用next()函数
In [3]: with open('/etc/passwd') as f:
...: try:
...: while True:
...: print(next(f)) #next()函数访问迭代中的函数
...: except StopIteration: #捕获结束异常
...: print('None') #通过指定返回结束值来判断迭代结束
In [28]: with open('/etc/passwd') as f:
...: while True:
...: line = next(f,None)
...: if line is None:
...: break
...: print(line)
2、委托迭代
class node(object):
def __init__(self,value):
self._value = value
self._children = [] def __repr__(self):
return 'Node({!r})'.format(self._value) def add_child(self,node):
self._children.append(node) def __iter__(self):
return iter(self._children) if __name__ == '__main__':
root = node(0)
child1 = node(1)
child2 = node(2)
root.add_child(child1)
root.add_child(child2)
for i in root:
print(i) #
Node(1)
Node(2)
3、用生成器创建新的迭代模式
def frange(start,stop,setup): #创建新的迭代函数
while start < stop:
yield start #通过yield转换成一个生成器
start += setup
#可根据要求生成迭代对象元素
for i in frange(0,10,0.8):
print(i)
4、实现迭代协议
class Node:
def __init__(self,value):
self._value = value
self._children = [] def __repr__(self):
return 'Node({!r})'.format(self._value) def add_child(self,node):
self._children.append(node) def __iter__(self):
return iter(self._children) def depth_first(self): #首先输出自己然后输出自己的子节点
yield self
for i in self:
yield from i.depth_first() if __name__ == '__main__':
root = Node(123)
child1 = Node(10)
child2 = Node(20)
root.add_child(child1)
root.add_child(child2)
child1.add_child(Node(111))
child1.add_child(Node(222))
child2.add_child(Node(333)) for i in root.depth_first():
print(i) #
Node(123)
Node(10)
Node(111)
Node(222)
Node(20)
Node(333)
5、反向迭代
In [29]: a = [1,2,3,4] In [30]: for i in reversed(a): #反向迭代
...: print(i)
...:
4
3
2
1
6、对迭代器做切片操作
#要对迭代器和生成器做数据切换处理,可以使用itertools.islice()函数
In [31]: def count(n):
...: while True:
...: yield n
...: n += 1
...:
In [33]: c = count(0)
#生成器对象时不可切片操作的
In [34]: c[10:20]
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-34-d27b6259daf3> in <module>()
----> 1 c[10:20] TypeError: 'generator' object is not subscriptable #只有使用itertools.islice()函数才可切片
In [35]: import itertools In [36]: for i in itertools.islice(c,10,20):
...: print(i,end=' ')
...:
10 11 12 13 14 15 16 17 18 19 #迭代器和生成器是没法执行普通的切片操作的,这是因为不知道它们的长度和索引,而islice()产生的结果是一个迭代器,它可以产生出所需要切片元素,它是通过访问并丢弃所有起始索引之前的元素来实现的,
#之后的元素会由islice对象来产生直到结束索引为止。并且islice()会消耗掉提供的迭代器中的数据,它只能访问一次的
7、跳过可迭代对象中的前一部分元素
#itertools模块中有一个函数dropwhile()它回迭代丢弃需要过滤的元素,但只丢弃开头的过滤元素
#cat test.txt #aaa
#bbb
ccc
ddd
#eee from itertools import dropwhile
#使用dropwhile函数过滤开始元素,startswith函数指定判断元素的值
with open('test.txt') as f:
for i in dropwhile(lambda x:x.startswith('#'),f):
print(i,end='') #输出结构只判断开始行中首字母为#好的行将过滤掉
ccc
ddd
#eee #也可用使用itertools模块中的islice函数来指定跳过多少个元素
from itertools import islice
items = ['a','b','c',1,2,3]
for x in islice(items,4,None):
print(x) #输出将跳过前面的4个元素,只输出后面的2,3 #如果需要跳过所有需要顾虑的元素,只需要指定判定规则值即可
with open('test.txt') as f:
lines = (line for line in f if not line.startswith('#'))
for line in lines:
print(line,end='') #输出就只有不以#号开头的行了
ccc
ddd
8、迭代所有可能的组合或排列
#itertools模块中提供了3个函数来解决所有元素的重排列的可能情况,先来看第一个itertools.permutations()使用方法:
In [6]: from itertools import permutations
In [7]: items = ['a','b','c']
In [8]: for i in permutations(items):
...: print(i)
...:
('a', 'b', 'c')
('a', 'c', 'b')
('b', 'a', 'c')
('b', 'c', 'a')
('c', 'a', 'b')
('c', 'b', 'a') #如果要限定排序的长度可用指定长度参数
In [9]: for i in permutations(items,2):
...: print(i)
....
('c', 'a')
('c', 'b') #使用第二个函数itertools.combinations()它将输出序列中所有元素的全部组合形式,但元素之间是不考虑顺序的,比如(a,b)和(b,a)是一种组合形式将只出现一次
In [12]: for j in combinations(range(4),3):
...: print(j)
...:
(0, 1, 2)
(0, 1, 3)
(0, 2, 3)
(1, 2, 3) In [13]: for j in combinations(range(4),4):
...: print(j)
...:
(0, 1, 2, 3) #第三个函数itertools.combinations_with_replacement()它允许一个元素可被选择多次进行排序
In [14]: from itertools import combinations_with_replacement In [15]: for i in combinations_with_replacement(range(1,3),3):
...: print(i)
...:
(1, 1, 1)
(1, 1, 2)
(1, 2, 2)
(2, 2, 2)
9、以索引-值对的形式迭代序列
#内建的enumerate()函数可用输出元素序列,可用指定序列的开始值
In [20]: for k,v in enumerate(my_list,1):
...: print(k,'==',v)
...:
1 == a
2 == b
3 == c #打印嵌套数组
In [21]: list1 = [(1,2),(11,22),(33,44)] In [22]: for n,(k,v) in enumerate(list1,1):
...: print(n,'<===>',k,v)
...:
1 <===> 1 2
2 <===> 11 22
3 <===> 33 44
10、同时迭代多个序列
#同时迭代多个序列可用使用zip()函数,它将迭代对象产生出一个元组,整个迭代的长度取其中最短的序列长度
In [23]: list1 = [1,2,3,4,5] In [24]: list2 = ['a','b','c','d'] In [25]: list3 = ['jar','py','jc'] In [26]: for x,y,z in zip(list1,list2,list3):
...: print(x,y,z)
...:
1 a jar
2 b py
3 c jc #如果需要输出完整的序列可以使用itertools模块中的zip_longest函数
In [27]: from itertools import zip_longest In [28]: for i in zip_longest(list1,list2,list3):
...: print(i)
...:
(1, 'a', 'jar')
(2, 'b', 'py')
(3, 'c', 'jc')
(4, 'd', None)
(5, None, None) #zip()通常用于处理数据配对的,如将以字典形式配对名称和值
In [29]: heard = ['name','age','salely'] In [30]: values = ['zhangsan',30,99999] In [31]: s = dict(zip(heard,values)) In [32]: s
Out[32]: {'name': 'zhangsan', 'age': 30, 'salely': 99999}
11、在不同的容器中进行迭代
#itertools.chain()方法可以在多个容器中迭代对象
In [33]: from itertools import chain In [34]: a = [1,2,3] In [35]: b = ['a','b','c'] In [36]: for i in chain(a,b):print(i)
1
2
3
a
b
c
12、创建处理数据的管道
import os,fnmatch,gzip,bz2,re def gen_find(filepat,top):
for path,dirlist,filelist in os.walk(top):
for name in fnmatch.filter(filelist,filepat):
yield os.path.join(path,name) def gen_opener(filenames):
for filename in filenames:
if filename.endswith('.gz'):
f = gzip.open(filename,'rt')
elif filename.endswith('.bz2'):
f = bz2.open(filename,'rt')
else:
f = open(filename,'rt')
yield f
f.close() def gen_concatenate(iterators):
for it in iterators:
yield from it def gen_grep(pattern,lines):
pat = re.compile(pattern)
for line in lines:
if pat.search(line):
yield line if __name__ == '__main__':
file_name = input('please in to file:')
directory_name = input('pease in to directory:')
lognames = gen_find(file_name,directory_name)
files = gen_opener(lognames)
lines = gen_concatenate(files)
pylines = gen_grep('(?i)python',lines)
for line in pylines:
print(line)
13、扁平化处理嵌套型的序列
#yield from可以将迭代对象中子元素进行递归,将它们所有的值产生出来,得到的结果就是一个没有嵌套的单值序列 from collections import Iterable def flatten(items,ignore_types=(str,bytes)):
for i in items:
if isinstance(i,Iterable) and not isinstance(i,ignore_types):
yield from flatten(i)
else:
yield(i) items = [1,2,[3,4,[5,6],7],8]
for i in flatten(items):
print(i,end=' ')
14、合并多个有序序列,再对整个有序序列进行迭代
#对多个有序序列先进行合并再进行排序,可以使用heapq.merge()函数,它不会将所有的数据读取到堆中,也不会做排序操作,
#它只是简单的检查每个输入序列中的第一个元素,将最小的发送出去,然后再重复执行这一步操作,直到序列耗尽为止 In [8]: import heapq In [9]: a = [12,3,4,9] In [10]: b = [5,32,15,1] In [11]: c = heapq.merge(a,b) In [12]: c
Out[12]: <generator object merge at 0x7f781eb934f8> In [13]: d = list(c) In [14]: d
Out[14]: [5, 12, 3, 4, 9, 32, 15, 1]
15、用迭代器取代while循环
#我们在处理I/O通信时经常会碰到接收数据时判断是否接收完的代码
def readder(s):
while True:
data = s.recv(8192)
if data == b'':
break
#上面的代码我们可以使用iter()函数来代替,它可以选择性的接收一个无参数的可调用对象和一个结束值作为输入,iter()会创建一个迭代器然后重复调用用户提供的可调用对象,知道它返回结束值 import sys
def reader(s):
for i in iter(lambda:s.recv(8192),b''):
data = sys.stdout.write(i)
print(data)
python3迭代器和生成器的更多相关文章
- Python3+迭代器与生成器
转载Python3 迭代器与生成器 迭代器 迭代是Python最强大的功能之一,是访问集合元素的一种方式. 迭代器是一个可以记住遍历的位置的对象. 迭代器对象从集合的第一个元素开始访问,直到所有的元素 ...
- python014 Python3 迭代器与生成器
Python3 迭代器与生成器迭代器迭代是Python最强大的功能之一,是访问集合元素的一种方式..迭代器是一个可以记住遍历的位置的对象.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结 ...
- python3: 迭代器与生成器(1)
1. 手动遍历迭代器 你想遍历一个可迭代对象中的所有元素,但是却不想使用for循环. >>> items = [1, 2, 3] >>> # Get the ite ...
- Python3 迭代器和生成器
想要搞明白什么是迭代器,首先要了解几个名词:容器(container).迭代(iteration).可迭代对象(iterable).迭代器(iterator).生成器(generator). 看图是不 ...
- Python3 迭代器与生成器 - 学习笔记
可迭代对象(Iterable) 迭代器(Iterator) 定义 迭代器和可迭代对象的区别 创建一个迭代器 创建一个迭代器类 使用内置iter()函数 StopIteration异常 生成器(gene ...
- Python3迭代器与生成器
迭代器 迭代是Python最强大的功能之一,是访问集合元素的一种方式. 迭代器是一个可以记住遍历的位置的对象. 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退 ...
- python3 迭代器,生成器
一 .什么是迭代 1. 重复 2.下次重复一定是基于上一次的结果而来 while True: cmd=input(':') print(cmd) l=[1,2,3,4] count=0 while c ...
- python系列九:python3迭代器和生成器
#!/usr/bin/python import sys '''迭代器是一个可以记住遍历的位置的对象.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退.迭代器有 ...
- 吴裕雄--天生自然python学习笔记:Python3 迭代器与生成器
迭代器 迭代是Python最强大的功能之一,是访问集合元素的一种方式. 迭代器是一个可以记住遍历的位置的对象. 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退 ...
随机推荐
- web项目部署在不同环境中需要修改配置文件的解决方法
web项目部署中存在的配置文件问题: web项目以war包的形式,部署在tomcat中,同时项目需要访问一些其他的东东,例如访问数据库,调用别的项目的API.在开发中,这些需要访问的外部地址通常以配置 ...
- express框架结合jade模板引擎使用
在views文件夹里新建一个jade.jade文件作为模板: html head title 哈哈 body #box ul li 标题1 li 标题2 li 标题3 li 标题4 #aside 在j ...
- Alpha冲刺测试
项目Alpha冲刺(团队) Alpha冲刺测试 姓名 学号 博客链接 何守成 031602408 http://www.cnblogs.com/heshoucheng/ 黄锦峰 031602411 h ...
- TCP/IP之蓟辽督师 转
原创: 刘欣 码农翻身 2016-11-07 本文续<TCP/IP之大明内阁>, 不了解背景的同学可以先看看上一篇文章, 当然这篇也是<TCP/IP之大明邮差>的前传, 主要讲 ...
- linux 修改终端颜色
要想修改终端的颜色,可以使用修改PS1环境变量的方式,也可以通过命令setterm来进行设置. 一.PS1 转自:修改linux终端命令行颜色 1.PS1 要修改linux终端命令行颜色,我们需要用到 ...
- CentOS修改主机名字
目录 查看hostnmae 修改hostname 远程别名/etc/hosts 查看hostnmae [root@centos ~]$ hostname centos 修改hostname [root ...
- SQL基本概念
目录 什么是SQL? DDL(Data Definition Language,数据定义语言) 创建数据库(CREATE) 创建表(CREATE) 删除表(DROP) 更新表(ALTER) DML(D ...
- 如何取消mysql的密码?
有两种方法: 1.mysql命令 SET PASSWORD FOR root@localhost=PASSWORD(''); 2.运行 mysqladmin 命令 mysqladmin -u roo ...
- 移动端web开发整理
/* 移动端定义字体的代码 */body { font-family: "Helvetica Neue", Helvetica; } ios端触摸时,会出现一个半透明灰色遮罩 如果 ...
- Day24-Ajax操作、图片验证码、KindEditor使用-转
参考源:http://blog.csdn.net/fgf00/article/details/54917439 三.Ajax操作 ajax操作基于浏览器的xmlHttpRequest对象,IE低版本是 ...