英文原文出处:Use More Iterators

本文介绍将代码转换为使用迭代器的原因和实用技巧。

我最喜欢的Python语言的特色之一是生成器,它们是非常有用的,然而当阅读开源代码时,我很少遇到它们。在这篇文章中,我希望概述它们最简单的实例去鼓励任何读者更多的使用它们。

阅读这篇文章的前提是你已经知道容器和迭代器是什么,我在之前的一篇博客文章中已经解释过这些概念,并详细阐述了我们通过更多的一些思考能获得什么。

Why?

为什么使用迭代器是一个好的方法?使用迭代器编程能避免使用中间变量,可以用更短的代码,运行轻松,消耗更小的内存,运行更快,组合性强,也更加漂亮。简而言之:它们更加优雅。

"The moment you've made something iterable, you've done something magic with your code. As soon as something's iterable, you can feed it to list(), set(), sorted(), min(), max(), heapify(), sum(), ‥. Many of the tools in Python consume iterators."

“当你做了一些可迭代的事情, 你已经为你的代码做了一些魔术。一旦它变得可迭代,你就能使用ist(), set(), sorted(), min(), max(), heapify(), sum()等函数,Python中的很多工具都使用迭代器。”

— Raymond Hettinger ([Transfroming Code into Beautiful, Idiomatic Python](https://www.youtube.com/watch?v=OSGv2VnC0go#t=825))

最近, Clojure为编程语言加了transducer, 这是一个与Python中的生成器非常相似的概念。(我强烈建议观看Rich Hickey 2014年在介绍它时在Strange Loop 的演讲:"Transduers" by Rich Hicky。)

在视频中, 他谈到把一个集合"puring"到另一个, 我认为这是一个动词, 非常直观地描述迭代器的性质与数据结构的关系。我将在未来的博客文章中更详细地写下这个想法。

Example

下面是一个常见的示例:

def get_lines(f):
result = []
for line in f:
if not line.startswith('#'):
result.append(line)
return result lines = get_lines(f)

现在看看用生成器写同样功能的代码:

def get_lines(f):
for line in f:
if not line.startswith('#'):
yield line lines = list(get_lines(f))

The Benefits

咋一看似乎没有太多不同之处,但是却有很多好处:

  • No bookkeeping(没有记录本). 你不需要创建一个空列表,然后一个个添加元素到里面,并返回它,这就少使用了一个变量;
  • Hardly consumes memory(几乎不耗内存). 无论输入文件有多大, 含迭代器的代码都不需要在内存中缓冲整个文件;
  • Works with infinite streams(可工作在无限流状态下).
  • Faster results(返回值更快). 可以立即得到返回结果, 而不是在读取整个文件之后;
  • Faster speed(运行速度更快). 第二段代码相比于第一段代码需要以初始方式创建列表运行的更快;
  • Composability(可组合性). 调用方式可以决定它如何使用返回结果。

最后一点也是最重要的,让我们深究它。

Composability

可组合性是关键之处。迭代器有着极强的组合性,在上面的例子中,列表是显性的创建,但是如果调用者需要一个集合呢?实际上,许多人要么写一个同样功能的基于集合的代码段,或者简单的调用函数set(),当然这是可行的,但是这非常浪费内存资源。再次想象一下这个文件很大,首先从这整个文件已经生成了一个很大的列表list,然后又使用set()通过这个列表在内存中生成一个所需要的集合set,那么原先的中间变量列表就是内存中的垃圾。

而对于使用生成器,函数只是发出“对象流”,调用者再决定将这些对象使用(puring)到什么数据类型中。

想要生成集合而不是列表?

uniq_lines = set(get_lines(f))

只想要文件中最长的一行吗?该文件将被完全读取, 但最多两行始终保存在内存中:

longest_line = max(get_lines(f), key=len)

只想要文件中的前10行吗?将从文件中读取不超过10行, 无论文件有多大:

head = list(islice(get_lines(f), 0, 10))

2013年在Pycon,Ned Batchelder 的演讲非常完美的阐述了我在这篇博文中所尝试解释的,我强烈推荐你们观看:Loop like a native: while, for, iterators, generators.

Summary

不要让中间变量在内存中存储数据,你几乎总是可以避开它们, 那么就可以获得可读性、速度、更小的内存占用空间和可组合性的回报。

< 完 >

转载请注明该译文原文链接: < https://www.cnblogs.com/tzhao/p/9874135.html >,谢谢!

Python中多使用迭代器的更多相关文章

  1. Python中生成器和迭代器的区别(代码在Python3.5下测试):

    https://blog.csdn.net/u014745194/article/details/70176117 Python中生成器和迭代器的区别(代码在Python3.5下测试):Num01–& ...

  2. python中“生成器”、“迭代器”、“闭包”、“装饰器”的深入理解

    python中"生成器"."迭代器"."闭包"."装饰器"的深入理解 一.生成器 1.生成器定义:在python中,一边 ...

  3. python中“生成器”、“迭代器”、“闭包”、“装饰器”的深入理解

    一.生成器 1.什么是生成器? 在python中,一边循环一边计算的机制,称为生成器:generator. 2.生成器有什么优点? 1.节约内存.python在使用生成器时对延迟操作提供了支持.所谓延 ...

  4. python中生成器及迭代器

    列表生成式 列表生成式是python内部用来创建list的一种方法,其格式形如: L = [x*8 for x in range(10)] print(L) 此时会得到结果:[0, 8, 16, 24 ...

  5. Python中生成器和迭代器的功能介绍

    生成器和迭代器的功能介绍 1. 生成器(generator) 1. 赋值生成器 1. 创建 方法:x = (variable for variable in iterable) 例如:x = (i f ...

  6. python中生成器与迭代器

    可迭代对象:一个实现了iter方法的对象是可迭代的 迭代器:一个实现了iter方法和next方法的对象就是迭代器 生成器都是Iterator对象,但list.dict.str虽然是Iterable(可 ...

  7. Python高级特性:迭代器和生成器

    在Python中,很多对象都是可以通过for语句来直接遍历的,例如list.string.dict等等,这些对象都可以被称为可迭代对象.至于说哪些对象是可以被迭代访问的,就要了解一下迭代器相关的知识了 ...

  8. Python高级特性:迭代器和生成器 -转

    在Python中,很多对象都是可以通过for语句来直接遍历的,例如list.string.dict等等,这些对象都可以被称为可迭代对象.至于说哪些对象是可以被迭代访问的,就要了解一下迭代器相关的知识了 ...

  9. Python中的迭代器和生成器

    本文以实例详解了python的迭代器与生成器,具体如下所示: 1. 迭代器概述: 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后 ...

随机推荐

  1. centOS下 JDK的三种安装方式

    由于各Linux开发厂商的不同,因此不同开发厂商的Linux版本操作细节也不一样,今天就来说一下CentOS下JDK的安装: 方法一:手动解压JDK的压缩包,然后设置环境变量 1.在/usr/目录下创 ...

  2. linux下通过sysfs操作GPIO

    linux下通过sysfs操作GPIO 在嵌入式设备中对GPIO的操作是最基本的操作.一般的做法是写一个单独驱动程序,网上大多数的例子都是这样的.其实linux下面有一个通用的GPIO操作接口,那就是 ...

  3. 如何用FFmpeg API采集摄像头视频和麦克风音频,并实现录制文件的功能

    之前一直用Directshow技术采集摄像头数据,但是觉得涉及的细节比较多,要开发者比较了解Directshow的框架知识,学习起来有一点点难度.最近发现很多人问怎么用FFmpeg采集摄像头图像,事实 ...

  4. java代码实现鼠标双击出现画图-----------paint()方法由系统自动调用,且一定是小写的字母p

    总结:在运行过程中,自己不是很认真,没有检查自己写的代码,结果是无论你怎么运行,双击 frame都没用,因为系统根本就没有调用paint()方法绘图.所以很重要的是实现这个方法 package com ...

  5. 分布式缓存系统 Memcached 数据存储slab与hashtable

    缓存数据以item为基本单元,以双链表形式存放在对应级别大小的slabclass结构的chunk中.同时该item还存放在链式hashtable中bucket中,用于提供快速查找的索引. 首先是理解缓 ...

  6. 在液晶屏里显示浮点数的方法 (sprintf 的妙用)

    思路:使用 sprintf 函数将浮点型数据转为指定格式的字符串 #include <stdio.h> #include<string.h> int main() { unsi ...

  7. Python实现SSH连接远程服务器

    首先需要安装paramiko模块 #-*- coding:utf-8 -*- __author__ = "MuT6 Sch01aR" import paramiko ssh = p ...

  8. Python中常见的异常处理

    异常和错误 part1:程序中难免出现错误,而错误分成两种 1. 语法错误(这种错误,根本过不了Python解释器的语法检测,必须在程序执行前就改正) # 语法错误示范一 if # 语法错误示范二 d ...

  9. leetcode812

    class Solution { public: double largestTriangleArea(vector<vector<int>>& points) { d ...

  10. python:if 语句的使用方法

    if-else类型: #if-else num = int(input("输入成绩!")) if num > 60: print ("及格") else: ...