新手学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 ...
随机推荐
- 00-Unit_Common综述-RecyclerView封装
自学安卓也有一年的时间了,与代码相伴的日子里,苦乐共存.能坚持到现在确实已见到了"往日所未曾见证的风采".今2018年4月2日,决定用一个案例:Unit_Common,把安卓基础的 ...
- 关于 form表单 嵌套问题的解决方案
我们经常是这样嵌套的: <form id="formId1" action="" method="post"> //表单1 &l ...
- RabbitMQ用户管理
rabbitmq常用命令 add_user <UserName> <Password> delete_user <UserName> chan ...
- 18. 4Sum(中等)
Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = tar ...
- 73. Set Matrix Zeroes(中等)
Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in place. 重点是空间复 ...
- JQuery 分页显示jquery-pager-1.0.js
原版是jquery-pager-1.0.js,经过变更修改加上按照项目中的一些需要修改过来. //初始化分页控件 PagerOptions为配置参数 url为要提交的url地址,如果不需要提交则可以为 ...
- Ubuntu安装与配置KVM
事前检查 查看一下linux是32位还是64位 file /bin/ls 确认一下 CPU支持硬件虚拟化(不支持也没关系,可以继续) egrep -o '(vmx|svm)' /proc/cpuinf ...
- FJUT寒假第一周作业浮点数查寻题解
二分强化——浮点数序列查询 TimeLimit:4000MS MemoryLimit:128MB 64-bit integer IO format:%I64d Problem Description ...
- PHP 字符串变量
PHP 字符串变量 字符串变量用于存储并处理文本. PHP 中的字符串变量 字符串变量用于包含有字符的值. 在创建字符串之后,我们就可以对它进行操作了.您可以直接在函数中使用字符串,或者把它存储在变量 ...
- Docker常见仓库Ubuntu
Ubuntu 基本信息 Ubuntu 是流行的 Linux 发行版,其自带软件版本往往较新一些. 该仓库提供了 Ubuntu从12.04 ~ 14.10 各个版本的镜像. 使用方法 默认会启动一个最小 ...