python-cookbook迭代器与生成器

迭代器与生成器的概念

  • 先搞清楚概念什么
  1. 迭代器
    很多容器比如list, tuple, dict, set等都可以使用for 循环,for语句会调用容器对像中有iter()函数,该函数返回一个next方法的迭代对像, 在python 中,只要定义了一个next方法,其实就是一个迭代器, 比如列表,字典,集合,字符串等
    用for取元素,遍历过程可以称为迭代,如果不想使用for,可以就可以使用iter(),next(), 没有元素后next()会引发StopIteration异常
s = 'abc'
for i in s:
    print(i)
ss = 'abc'
it = iter(ss) # 调用容器的iter函数
print(it) # <str_iterator object at 0x110441410>
print(next(it)) #a 使用next()内置函数来调用__next__()方法
print(next(it)) #b
print(next(it)) #c
print(next(it))  #StopIteration 引发异常
  1. 生成器
    列表数据如果太大, 比如一个列表包含100W的元素而我们只需要前面几个元素,那么该列表的空间是不是就浪费掉了呢? 为了优化这种问题,可以考虑下假如列表元素可以按照某算法推算出来, 那么我们是不是可以在循环过程中不断推算出后续的元素呢,这样就不需要再创建完整的list, 从而节省了空间, 这种方式其实就是生成器,与迭代器类似于包含与被包含的关系,生成器就是一种迭代器. 不过在迭代过程中只能迭代一次,因为它们并不是把所有值存在内存中,而是在运行时才会生成值啊.

迭代器并不返回一个值,而是yield一个值

def generat(data):
    for index in range(len(data)-1, -1, -1):
        yield data[index]
for char in generat('golf'):
    print(char)
  • 生成器表达式
print(sum(i*i for i in range(10))) #285
x = [1,2,3]
y = [4,5,6]
print(sum(x*y for x,y in zip(x,y)))

跳过可迭代对象的开始部分

  • 想遍历一个可迭代对像,但对刚开始的一些元素不感兴趣,比如/etc/passwd中的##号,这个时候可以使用itertools.dropwhile()函数
from itertools import dropwhile
with open('/etc/passwd') as f:
#     for line in f:
#         print(line, end= '')
    for line in dropwhile(lambda line: line.startswith('#'),f ):  #dropwhile()接受一个函数或者可迭代对像
        print(line, end='')  

排列组合的迭代

  • eg: 想迭代遍历一个集合中元素的所有可能的排列或者组合,可以使用itertools模块中的方法
from itertools import permutations
items =['a','b', 'c']
# 打乱集合中元素排列顺序生成一个元组
for p in permutations(items):
    print(p)
# 输出
# ('a', 'b', 'c')
# ('a', 'c', 'b')
# ('b', 'a', 'c')
# ('b', 'c', 'a')
# ('c', 'a', 'b')
# ('c', 'b', 'a')
for pP in permutations(items,2): #得到指定长度的所有排列
    print(pP)
# ('a', 'b')
# ('a', 'c')
# ('b', 'a')
# ('b', 'c')
# ('c', 'a')
# ('c', 'b')

# combinations 可得到输入集合中元素的所有的组合
for c in combinations(items,3):
    print(c) #('a', 'b', 'c')

for cc in combinations(items,2):
    print(cc) # ('a', 'b')
#('a', 'c')
#('b', 'c')

序列上索引值迭代

  • 想在迭代一个序列的同时跟踪正在被处理的元素索引,可以使用enumerate()函数
my_list = ['a','b','c']
for idx, val in enumerate(my_list):
    print(idx,val) 
# 0 a
# 1 b
# 2 c
#如果你想将一个文 件中出现的单词映射到它出现的行号上去,可以很容易的利用 enumerate() 来完成
word_summary = defaultdict(list)
# 每个单词对应一个Key,值为出现的次数,当然 下面分隔单词的情况具体还要看文本是什么样子, 使用正则区分会比较好
with open('/Users/yjoqm/billboard.txt', 'r') as f:
   lines = f.readlines()
for idx, line in enumerate(lines):
#     words = [w.strip().lower() for w in line.strip()]
   words = [w for w in line.strip().split(' ')]
   print(words)
   for word in words:
       word_summary[word].append(idx)
print(word_summary)
# defaultdict(<class 'list'>, {'{': [0, 3], '"code":': [1], '0,': [1], '"time":': [2], '1559136497,': [2], '"data":': [3]

同时迭代多个序列

  • 想同时迭代多个序列,每次分别从一个序列中取一个元素,使用zip()
xpts =[1, 5,4, 2,10,7]
ypts =[101, 78, 37,15, 62,99]
for x,y in zip(xpts, ypts):
    print(x,y)
#itertools.zip_longest()为zip函数的补充,可以设置缺失字段的默认值,比如  zip_longest(a,b,fillvalue=0)
# 可以zip打包,然后使用dict(zip())转换成字典进行处理。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,525评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,203评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,862评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,728评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,743评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,590评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,330评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,244评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,693评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,885评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,001评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,723评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,343评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,919评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,042评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,191评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,955评论 2 355