新手学python(3):yield与序列化
1 Yield生成器
Yield是我在其他语言中没有见过的一个属性,算是python的一大特色,用好之后可以使代码更简洁。考虑一个简单的例子,文件的遍历。要遍历一个目录下的所有文件需要递归的操作。如果我们只是单纯的打印文件名,我们可以在递归的过程中完成,每当发现一个非目录就可以打印文件名。代码如下:
class TraverseDirectory(object):
@staticmethod
def traverse(dir):
if os.path.isdir(dir):
files=os.listdir(dir);
for file in files[::-1]:
full_name=os.path.join(dir,file);
TraverseDirectory.traverse(full_name):
else:
print dir;
但是如果我们想保存文件名或者对每一个文件执行更复杂的操作返回一个结果,情况就稍微有些复杂。问题在于我们需要一个全局变量保存访问的结果。例如在遍历到一个文件时获取其文件大小,则我们还需要一个dictionary结构:
class TraverseDirectory(object):
fileSize=dict();
@staticmethod
def traverse(dir):
if os.path.isdir(dir):
files=os.listdir(dir);
for file in files[::-1]:
full_name=os.path.join(dir,file);
TraverseDirectory.traverse(full_name);
else:
TraverseDirectory.fileSize[dir]=os.path.getsize(dir);
初看代码感觉其实也不复杂,只是多了一个变量而已。在多数情况下确实如此,但是从应用角度来看上述代码稍有不足:为了访问遍历的结果,我们需要访问该类的全局变量或者一个静态变量,正如我们在其他语言中一样,为此我们还需要一个get函数。但是,这还不是最严重的问题,fileSize占用的空间才是问题!
上述递归函数只有在遍历完所有的文件之后我们才能访问fileSize结构。这就意味着如果目录很大,则fileSize也会非常大,如果要控制内存占用,上述方式会很不好。此时,就可以采用yield生成器完成遍历。
何谓生成器?其实很简单,概念和迭代器类似,都是为了遍历而存在。迭代器是为了遍历变量,例如列表、元组、字典等等。生成器不是遍历变量,而是函数。简而言之,包含yield语句的函数会被特地编译成生成器。当函数被调用时,他们返回一个生成器对象,这个对象支持迭代器接口。不像一般的函数会生成值后退出,生成器函数在生成值后会自动挂起并暂停他们的执行和状态,他的本地变量将保存状态信息,这些信息在函数恢复时将再度有效。我们可以将生成器理解成可以随时获得函数返回值的迭代器。可以将生成器与gdb调试器对比,我们在每一步单步调试的过程中,系统中总会有许多变量和其运行时值,yield就对应每一次的单步调试,并获取当前的变量值,不过其获取返回值是在每一次递归结束时。将上述遍历代码改成yield方式之后为:
class TraverseDirectory(object):
@staticmethod
def traverse(dir):
if os.path.isdir(dir):
files=os.listdir(dir);
for file in files[::-1]:
full_name=os.path.join(dir,file);
for results in TraverseDirectory.traverse(full_name):
yield results;
else:
yield {dir:os.path.getsize(dir)};
与之前的代码相比,就是少了一个变量,然后多了两个yield。通过这个微小的变化,我们去掉了函数的内存大小限制,也使代码更简洁。需要注意的一点是,调用过程也很简单,因为函数是一个生成器,具有迭代器的功能,我们就可以利用for循环去遍历函数的返回值。
Yield这种具有中断功能的设计使代码更加简洁,但是对效率会有一定影响。瑕不掩瑜,建议大家熟练应用yield。
2 序列化
在进行网络通信的过程中,我们传递的是没有含义的数据流,这就意味着我们无法直接传递list和dict之类的数据结构,而需要首先将它们序列化之后再进行传递。接收方收到数据流之后再发序列化获得原始的数据结构。序列化的应用并不局限于网络通信,在持久化存储中也需要用到序列化。
Python中有两个关于序列化的库:json和cPickle,两者用法相同,但是貌似json速度更快,因而json使用的次数更多。序列化调用dumps,反序列化调用loads,使用非常简单。
如果需要序列化的数据编码方式不是默认方式,我们还可以指定编码方式:
result=json.dumps(data,ensure_ascii=True,encoding=’gbk’);
反序列化也需要指定编码方式:
result=json.loads(data, encoding=’gbk’);
由于序列化操作在python中非常简单,在此不做更多介绍,更加深入的操作请参考:Json概述以及python对json的相关操作。
新手学python(3):yield与序列化的更多相关文章
- 【新手学Python】一、基础篇
由于以前处理数据用Matlab和C,最近要处理大量文本文件,用C写实在是太繁琐,鉴于Python的强大文本处理能力,以及其在Deep Learning上有着很大优势,本人打算从即日起学习Python, ...
- 新手学python(1):解析XML与系统调用
最近需要做一个项目,完成一批音乐的格式转换.由于之前并未学习过python,所以想借此机会学一下.在介绍自己的学习过程之前,先把项目简要描述一下.目前在一台服务器a上有几十万首原始的MP3音乐文件,现 ...
- 新手学python(2):C语言调用完成数据库操作
继续介绍本人的python学习过程.本节介绍如何利用python调用c代码.内容还是基于音乐信息提取的过程,架构如图一.Python调用c实现的功能是利用python访问c语言完成mysql数据库操作 ...
- 零基础怎么学Python编程,新手常犯哪些错误?
Python是人工智能时代最佳的编程语言,入门简单.功能强大,深获初学者的喜爱. 很多零基础学习Python开发的人都会忽视一些小细节,进而导致整个程序出现错误.下面就给大家介绍一下Python开发者 ...
- 简学Python第二章__巧学数据结构文件操作
#cnblogs_post_body h2 { background: linear-gradient(to bottom, #18c0ff 0%,#0c7eff 100%); color: #fff ...
- 简学Python第一章__进入PY的世界
#cnblogs_post_body h2 { background: linear-gradient(to bottom, #18c0ff 0%,#0c7eff 100%); color: #fff ...
- 小白学PYTHON时最容易犯的6个错误,看看你遇到过几个
最近又在跟之前的同学一起学习python,一起进步,发现很多测试同学在初学python的时候很容易犯一些错误,特意总结了一下.其实这些错误不仅是在学python时会碰到,在学习其他语言的时候也同样会碰 ...
- [ZZ]新手学 appium-合集第一季度
原文地址: https://testerhome.com/topics/2599 新手学appium-合集第一季度地址如下: 1.新手学 appium-GUI 端搞起来:http://testerho ...
- 投入机器学习的怀抱?先学Python吧
前两天写了篇文章,给想进程序员这个行当的同学们一点建议,没想到反响这么好,关注和阅读数都上了新高度,有点人生巅峰的感觉呀.今天趁热打铁,聊聊我最喜欢的编程语言——Python. 为什么要说Python ...
随机推荐
- 动态规划--Kin
动态规划: 1.最大子序列和 2.LIS最长递增子序列 3.LCS最长公共子序列 4.矩阵连乘 5.数字金字塔 1.最大子序列和 #include<iostream> using name ...
- c# 操作数据库
查询 string strConnection = "Data Source=(local);Initial Catalog=zpractice;Integrated Security=SS ...
- springboot解决跨域问题(Cors)
1.对于前后端分离的项目来说,如果前端项目与后端项目部署在两个不同的域下,那么势必会引起跨域问题的出现. 针对跨域问题,我们可能第一个想到的解决方案就是jsonp,并且以前处理跨域问题我基本也是这么处 ...
- WPF TextBlock 判断 isTextTrimmed 文本是否超出
WPF TextBlock 设置TextTrimming情况下 判断 isTextTrimmed(Text 文本是否超出 是否出现了省略号) private bool HasTextTrimmed(T ...
- python学习之路网络编程篇(第二篇)
新课程知识的引入:python作用域 #python中无块级别作用域 if 1 == 1 : name = 'alex' print(name) for i in range(10): name = ...
- python学习之路基础篇(三)
博客参考:http://www.cnblogs.com/wupeiqi/articles/4943406.html http://www.cnblogs.com/luotianshuai/p/4949 ...
- 通讯协议序列化解读(一) Protobuf详解教程
前言:说到JSON可能大家很熟悉,是目前应用最广泛的一种序列化格式,它使用起来简单方便,而且拥有超高的可读性.但是在越来越多的应用场景里,JSON冗长的缺点导致它并不是一种最优的选择. 一.常用序列化 ...
- 解读Batch Normalization
原文转自:http://blog.csdn.net/shuzfan/article/details/50723877 本次所讲的内容为Batch Normalization,简称BN,来源于<B ...
- Bootstrap3 表格-鼠标悬停
通过添加 .table-hover 类可以让 <tbody> 中的每一行对鼠标悬停状态作出响应. <table class="table table-hover" ...
- linux TCP数据包封装在SKB的过程分析
在linux中 tcp的数据包的封装是在函数tcp_sendmsg开始的,在函数tcp_sendmsg中用到skb = sk_stream_alloc_skb(sk, select_size(sk, ...