IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> python生成器与迭代器(配套相关案列解析用法) -> 正文阅读

[Python知识库]python生成器与迭代器(配套相关案列解析用法)

一.python生成器简介

在 Python 中,使用了 yield 的函数被称为生成器(generator)。跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。
生成器的主要作用:

  • 可是当我们的数据特别大的时候建立一个列表的储存数据就会很占内存的。这时生成器就派上用场了。它可以说是一个不怎么占计算机资源的一种方法。
  • 生成器可以有效的减小一些数据处理过程的内存使用;
  • 生成器一次只能产生一个值,这样消耗的内存数量将大大减小,而且允许调用函数可以很快的处理前几个返回值;
  • 因此生成器看起来像是一个函数,但是表现得却像是迭代器

二.python生成器案列

2.1 生成器表达式

##列表生成式
L = [x*x for x in range(10)]
print(L)
##生成器
g = (x*x for x in range(10))
print(g)

output:
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
<generator object <genexpr> at 0x7f91487794c0>

要创建一个generator,最简单的方法就是,只有把一个列表生成式的[]中括号改为()小括号,就创建一个generator。
由于generator保存的是算法,每次调用next(generaotr_ex)就计算出他的下一个元素的值,直到计算出最后一个元素,没有更多的元素时,抛出StopIteration的错误,而且上面这样不断调用是一个不好的习惯,正确的方法是使用for循环,因为generator也是可迭代对象,生成器在本质上是可迭代的。

g = (x*x for x in range(10))
print(g)
for n in g:
    print(n)

<generator object <genexpr> at 0x7f9148475e08>
0
1
4
9
16
25
36
49
64
81

2.2生成器函数

  • 生成器函数打印斐波那契数列
## 利用生成器打印输出斐波那契数列
def fib(max):
    n,a,b = 0,0,1
    while n < max:
        yield b
        a,b = b,a+b
        n =n+1
f = fib(7)
print(f)
for n in f:
    print(n)

output:

<generator object fib at 0x7f9148475f68>
1
1
2
3
5
8
13

  • 生成器函数打印杨辉三角
###利用生成器,打印输出杨辉三角(思路一)
def triangle():
    _list,new_list = [],[]
    while True:
        if len(_list) == 0:
            new_list.append(1)
        else:
            for i in range(len(_list)+1):
                if i ==0:
                    new_list.append(1)
                elif i == len(_list):
                    new_list.append(1)
                else:
                    new_list.append(_list[i-1]+_list[i])
        yield new_list ##返回生成值,函数挂起
        _list = new_list.copy()##下一次调用后从断点继续执行
        new_list = []
def triangle_print():
    n = 0
    for t in triangle():
        n = n + 1
        print(t)
        if n == 12:
            break
triangle_print()


###利用生成器,打印输出杨辉三角(思路二)
def triangles():
    m = [1]
    while True:
        yield m
        m = [1] +[m[x]+m[x+1] for x in range(len(m)-1)] +[1]
        
def triangles_print():
    n = 0
    for t in triangles():
        n = n + 1
        print(t)
        if n == 11:
            break
triangle_print()

output:
[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]
[1, 4, 6, 4, 1]
[1, 5, 10, 10, 5, 1]
[1, 6, 15, 20, 15, 6, 1]
[1, 7, 21, 35, 35, 21, 7, 1]
[1, 8, 28, 56, 70, 56, 28, 8, 1]
[1, 9, 36, 84, 126, 126, 84, 36, 9, 1]
[1, 10, 45, 120, 210, 252, 210, 120, 45, 10, 1]
[1, 11, 55, 165, 330, 462, 462, 330, 165, 55, 11, 1]

三.python生成器的具体应用

3.1 python生成器在文本数据预处理中的应用

对于一些文本字符数据,我们需要对其进行分词,正则清洗,分割等一系列文本预处理操作。我们利用函数生成器来获取预处理结果将会很大程度上减小项目内存。

import re

def load_stopwords():
    """
    加载停用词
    :return:
    """
    sw = set()
    with open("train/stop_word.txt", 'r') as f:
        for line in f.readlines():
            sw.add(line[:-1])
    return sw

# 文本预处理生成器函数
def word_lemmatize(context):
    stopword = ['at','based','in','of','for','on','and','to','an','using','with','the','by','we','be','is','are','can','or','no','from','like']
    stopword1 = load_stopwords() 
    context = re.sub('[^a-zA-Z]', ' ', context).strip().lower().split()
    for word in context:
        if word not in stopword and word not in stopword1 and len(word)> 2:
            yield word
            
if __name__ == '__main__':          
    pstr ='Trypanosoma cruzi DNA replication includes the sequential recruitment of pre-replication and replication machineries close to nuclear periphery'            
    print(' '.join(word_lemmatize(pstr)).strip().lower().split())

output:
['trypanosoma', 'cruzi', 'dna', 'replication', 'includes', 'sequential', 'recruitment', 'pre', 'replication', 'replication', 'machineries', 'close', 'nuclear', 'periphery']

3.2 NLP词向量训练

在使用一些包训练词向量的过程中往往需要加载很大的语料,如果服务器内存比较小的话,往往加载大一些的语料都没法实现,更不用说训练语料了。因此需要利用生成器一点一点读取语料。
当数据集特别大的时候,直接加载大语料就需要消耗特别多的内存,gensim等词向量训练工具包支持使用迭代生成器的方式输入。

比如,我们利用生成器逐个读取lmdb数据库中的文本数据,gensim迭代生成器来训练。

'''利用生成器读取语料,并训练的一般写法'''
class MySentences(object):
    def __init__(self, dirname):
        self.dirname = dirname
 
    def __iter__(self):
        for fname in os.listdir(self.dirname):
            for line in open(os.path.join(self.dirname, fname)):
                yield line.split()
 
sentences = MySentences('/some/directory') # 第二种输入方式:占用内存少的迭代器
model = Word2Vec(sentences)


'''生成器从lmdb加载语料,并且迭代训练'''
class MySenteces1():
    def __init__(self, dirname):
        self.LMDB_NAME = dirname
        self.lc = LMDBClient(self.LMDB_NAME)
        

    def __iter__(self):
        with self.lc.db.begin() as txn:
            for k in txn.cursor():
                author_feature = data_utils.deserialize_embedding(k[1])
                random.shuffle(author_feature)
                yield author_feature

class Word2vecModel:

    def __init__(self, name="sci_alldata"):
        self.model = None
        self.name = name


    def train(self, wf_name, size=EMB_DIM):
        data = MySenteces1('sci_all_data_feature')
        self.model = Word2Vec(data,size=100,negative =5, min_count=2, window=5,workers=16)
        self.model.save(join(settings.EMB_DATA_DIR, '{}.emb'.format(wf_name)))

3.3 生成器用于将字典分割成多个字典

对于一个比较大的字典数据集,我们需要按照一定的补偿分割成多个字典进行分块处理。比如多进程处理数据,就需要把一个数据集分成多个,每个进程处理一部分。

import json 
import multiprocessing
import pandas as pd
from os.path import join


def load_json(rfdir, rfname):
    with codecs.open(join(rfdir, rfname), 'r', encoding='utf-8') as rf:
        return json.load(rf)

def chunks(data, SIZE=1000):
    for i in range(0, len(data), SIZE):
        yield dict(list(data.items())[i:i+SIZE])

if __name__ =='__main__':
    ##加载需要消歧的数据
    name_pubs = load_json('data', 'sci_author_data_50_all.json')
    print('同名论文集数量为:',len(name_pubs))
    processor = 10
    p = multiprocessing.Pool(processor)
    for i,item in enumerate(chunks(name_pubs,28000)):
#         name_pub =item
#         if i in [0,1,2,3,4]:
        p.apply_async(disambiguate, args=(item,i,))
    p.close()
    p.join()
    print('程序 总用时 :',datetime.now()-start_time)

四.python迭代器

4.1 python迭代器简介(主要是相关概念的理解)

我们已经知道,可以直接作用于for循环的数据类型有以下几种:一类是集合数据类型,如list、tuple、dict、set、str等;一类是generator,包括生成器和带yield的generator function。这些可以直接作用于for循环的对象统称为可迭代对象:Iterable。

  • 生成器不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了。
  • 生成器一定是迭代器对象;
  • 可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator;
  • list、dict、str,tuple,set等虽然是Iterable,却不是Iterator对象;
  • 把list、dict、str等Iterable变成Iterator可以使用iter()函数;
  • 凡是可作用于for循环的对象都是Iterable类型;
  • 凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;
  • Iterator对象是Iterable对象,而Iterable对象不一定是Iterator对象;
>>> isinstance(iter([]), Iterator)
True
>>> isinstance(iter('abc'), Iterator)
True

4.2 为什么list、dict、str等数据类型不是Iterator?

因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。

Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。
总结:可迭代对象(Iterable)一般序列长度都是已知的,而迭代器对象不能提前知道序列的长度,Iterator可以表示一个无限大的数据流,一直迭代下去。

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2021-07-28 16:32:42  更:2021-07-28 16:32:50 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年4日历 -2024/4/26 14:37:10-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码