赞
踩
1.当一个函数中带有yield关键字之后,这个函数就变成了一个生成器。当我们直接调用它时,返回的是一个生成器对象。
2.那么既然它是一个生成器,那么我们可以通过循环来调用它,来执行它内部的逻辑。那么关键来了,带yield关键字的生成器它的执行逻辑是怎样的呢?
总结来说那就是当我们在外部循环调用该生成器时,每次遇到yield关键字时,返回其后面的的返回值,一次循环结束,然后程序会停在这个地方。然后下一次循环开始的时候,程序会从上一次停止的地方开始继续执行,知道再次遇到yield关键字,返回结果,该次循环结束,程序再次停止在该地方。也就是说每一次遇到yield,就意味着完成一次循环过程,返回一个对象。当生成器循环结束时,经历几个yield关键字,就意味着生成器经历几轮的循环,返回几个对象。下面举一个简单的例子
def generator():
for i in range(10):
yield i
yield 11
yield 12
在这个生成器中,我首先定义了一个循环体,让它能够产生0-10之间的整数,然后我又单独定义了两个yield来生成11和12。如果我们在外部通过for循环来遍历这个生成器,最终就会生成0-12的遍历结果,对应着生成器内部的12个yield对象。
[i for i in generator()]
#执行结果
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12]
在做机器学习项目时,必不可少的就是数据的读取。但是很多时候,特别是文本类型的数据,一条数据存储在多行中,而且行数各不相同。唯一的分隔就是一个空行。这个时候使用yield来循环读取数据就非常方便。下面展示了一个用yield定义生成器来读取conll文本数据。
首先先来看一下原始的文本格式:
每两条数据之间都通过一个空行隔开,每条数据包括文本(地址)以及标签(地址要素)中间用空格分开。OK,那我们具体该怎么读取每条数据呢?下面是我定义的一个读取函数(生成器)
#定义生成器读取conll格式文件 def read_conll_file(file_name): current_words = [] current_tag_classes = [] with open(file_name, encoding='utf-8') as conll: for line in conll: line = line.strip() if line: word,tag_class = line.split(' ') current_words.append(word) current_tag_classes.append(tag_class) else: yield (current_words, current_tag_classes) current_words = [] current_tag_classes = [] #将最后一部分buffer内容输出,针对文件最后一行非空的情况 if current_tag_classes != []: yield (current_words, current_tag_classes) #读取训练集和验证集 train_set=[(words,tag_classes) for (words,tag_classes) in read_conll_file('train.conll')] dev_set=[(words,tag_classes) for (words,tag_classes) in read_conll_file('dev.conll')] len(train_set),len(dev_set) # 结果 (8856, 1970)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。