新手学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 ...
随机推荐
- sharepoint环境安装
SharePoint 2013 测试环境安装配置指南 软件版本 Windows Server 2012 标准版 SQL Server 2012 标准版 SharePoint Server 2013 企 ...
- java中如何在代码中判断时间是否过了10秒
long previous = 0L; ... { Calendar c = Calendar.getInstance(); long now = c.getTimeInMillis(); //获取当 ...
- IOS和OSX事件传递机制
本文ios部分转载自: http://zhoon.github.io/ios/2015/04/12/ios-event.html iOS的事件有好几种:Touch Events(触摸事件).Motio ...
- Mysql锁机制--读锁
Mysql 系列文章主页 =============== 1 准备数据 1.1 建表 1.1.1 建立 Employee表 DROP TABLE IF EXISTS employee; CREATE ...
- iframe嵌套页面 音频在微信公众号环境无法播放
在微信公众号中 没有iframe的时候window.WeixinJSBridge为对象,有iframe时为undefined 要使用 window.parent.WeixinJSBridge得到 if ...
- FreeMarker学习教程
copy自http://demojava.iteye.com/blog/800204 以下内容全部是网上收集: FreeMarker的模板文件并不比HTML页面复杂多少,FreeMarker模板文件主 ...
- include和require的区别比较
require 的使用方法如 require("MyRequireFile.php"); .这个函数通常放在 PHP 程序的最前面,PHP 程序在执行前,就会先读入 require ...
- aways on 配置部署(二)——配置域
前一篇中我们基本了解了配置aways on的三个步骤,本篇就具体讲解如何配置域. DNS的配置 上篇可以看到三台服务器的ip地址,网关,DNS等配置,其中sqlDNS服务器的dns为自己的ip地址,s ...
- 如何搭建ssh服务?
为了日后便于查询,本文所涉及到的所有命令集合如下: rpm -qa | grep openssh #查看是否安装了openssh软件 service sshd status #服务端的ssh状态 if ...
- ACM 排列2
Ray又对数字的列产生了兴趣: 现有四张卡片,用这四张卡片能排列出很多不同的4位数,要求按从小到大的顺序输出这些4位数. Input每组数据占一行,代表四张卡片上的数字(0<=数字<=9 ...