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与序列化的更多相关文章

  1. 【新手学Python】一、基础篇

    由于以前处理数据用Matlab和C,最近要处理大量文本文件,用C写实在是太繁琐,鉴于Python的强大文本处理能力,以及其在Deep Learning上有着很大优势,本人打算从即日起学习Python, ...

  2. 新手学python(1):解析XML与系统调用

    最近需要做一个项目,完成一批音乐的格式转换.由于之前并未学习过python,所以想借此机会学一下.在介绍自己的学习过程之前,先把项目简要描述一下.目前在一台服务器a上有几十万首原始的MP3音乐文件,现 ...

  3. 新手学python(2):C语言调用完成数据库操作

    继续介绍本人的python学习过程.本节介绍如何利用python调用c代码.内容还是基于音乐信息提取的过程,架构如图一.Python调用c实现的功能是利用python访问c语言完成mysql数据库操作 ...

  4. 零基础怎么学Python编程,新手常犯哪些错误?

    Python是人工智能时代最佳的编程语言,入门简单.功能强大,深获初学者的喜爱. 很多零基础学习Python开发的人都会忽视一些小细节,进而导致整个程序出现错误.下面就给大家介绍一下Python开发者 ...

  5. 简学Python第二章__巧学数据结构文件操作

    #cnblogs_post_body h2 { background: linear-gradient(to bottom, #18c0ff 0%,#0c7eff 100%); color: #fff ...

  6. 简学Python第一章__进入PY的世界

    #cnblogs_post_body h2 { background: linear-gradient(to bottom, #18c0ff 0%,#0c7eff 100%); color: #fff ...

  7. 小白学PYTHON时最容易犯的6个错误,看看你遇到过几个

    最近又在跟之前的同学一起学习python,一起进步,发现很多测试同学在初学python的时候很容易犯一些错误,特意总结了一下.其实这些错误不仅是在学python时会碰到,在学习其他语言的时候也同样会碰 ...

  8. [ZZ]新手学 appium-合集第一季度

    原文地址: https://testerhome.com/topics/2599 新手学appium-合集第一季度地址如下: 1.新手学 appium-GUI 端搞起来:http://testerho ...

  9. 投入机器学习的怀抱?先学Python吧

    前两天写了篇文章,给想进程序员这个行当的同学们一点建议,没想到反响这么好,关注和阅读数都上了新高度,有点人生巅峰的感觉呀.今天趁热打铁,聊聊我最喜欢的编程语言——Python. 为什么要说Python ...

随机推荐

  1. PostgreSQL 查看单表大小

    1. 在数据库中查单个表 select pg_size_pretty(pg_relation_size('table_name')); 2. 查出并按大小排序 SELECT table_schema ...

  2. java中如何在代码中判断时间是否过了10秒

    long previous = 0L; ... { Calendar c = Calendar.getInstance(); long now = c.getTimeInMillis(); //获取当 ...

  3. 一个成功的 Git 分支模型(适用于商业应用开发)

    在这篇文章中,我将推广一下大约一年前我介绍过的一些项目(公私皆有)中使用的开发模型,它们的结果都非常成功.有段时间我非常想写出来分享一下,但是我至今才抽出时间来.我不会言及任何项目细节,仅讨论分支策略 ...

  4. java处理数据库不支持的emoji

    一般数据库的编码是utf8,utf8是不支持存储表情符的,当存入的微信昵称带有表情符时就会出现乱码情况,有两种解决方法: 1.mysql数据库升级到5.5版本以上,utf8改为utf8mb4,utf8 ...

  5. Python中的str与unicode处理方法

    Python中的str与unicode处理方法 2015/03/25 · 基础知识 · 3 评论· Python 分享到:42 原文出处: liuaiqi627 的博客    python2.x中处理 ...

  6. git提交项目常用命令及git分支的用法

    1.第一步首先从git托管平台clone项目,我这里就使用idea为例: 填写git的url与存放本地目录名及项目名     2.如果你对项目进行了一些修改,就可以执行git命令,进行提交. 有两种方 ...

  7. Python3 注释

    确保对模块, 函数, 方法和行内注释使用正确的风格 Python中的注释有单行注释和多行注释: Python中单行注释以#开头,例如: #!/usr/bin/python3 #coding=utf-8 ...

  8. Java第10次实验(数据库)

    参考资料 数据结构实验参考文件 MySql操作视频与数据库相关jar文件请参考QQ群文件. 第1次实验 1. MySQL数据库基本操作 完整演示一遍登录.打开数据库.建表.插入 常见错误:语句后未跟; ...

  9. cassandra 3.x官方文档(4)---分区器

    写在前面 cassandra3.x官方文档的非官方翻译.翻译内容水平全依赖本人英文水平和对cassandra的理解.所以强烈建议阅读英文版cassandra 3.x 官方文档.此文档一半是翻译,一半是 ...

  10. Android线性布局

    线性布局 LinearLayout 是一个视图组,用于使所有子视图在单个方向(垂直或水平)保持对齐. 您可以使用 android:orientation 属性指定布局方向. LinearLayout ...