尽管while和for循环能够执行大多数重复性任务, 但是由于序列的迭代需求如此常见和广泛, 以至于Python提供了额外的工具以使其更简单和高效. 迭代器在Python中是以C语言的速度运行的, 而且迭代器的版本根据每次发行而改进, 所以它的运行速度更快.

while一般比for的效率更低些, for循环通过不同的写法可以完全可以替代while循环, 所以当在while和for中选择时,用for循环吧

迭代器

迭代器初探

for循环可以用于Python中任何序列类型, 包括列表以及元组以及字符串. 实际上for循环更加通用:可用于任何可迭代对象.实际上, python中所有的会从左到右扫描对象的迭代工具都是如此通用, 这些迭代工具包括 for循环, 列表解析, in成员关系测试, map内置函数等

>>> for i in [1, 2, 3]:print(i, end=' ')

1 2 3

>>> for i in (1, 2, 3):print(i, end=' ')

1 2 3

>>> for i in "apple":print(i, end=' ')

a p p l e

可迭代对象

序列概念的通用化,如果对象是实际保存的序列或者迭代环境中一次产生一个结果的对象, 就可以看做是可迭代的

文件迭代器

看看迭代器和内置类型如何工作的,例如文件, 已经打开的文件对象有个方法readline(), 可以一次从文本中读取下一行(包括行末标识符)到一个字符串, 每次调用readline(),就会前进到下一行, 到达文件末尾返回空字符串, 我们通过它来检测, 从而跳出循环.

>>> f = open("/Users/mac/Documents/path.py")

>>> f.readline()

'import sys\n'

>>> f.readline()

'print(sys.path)\n'

>>> f.readline()

'print("hello heathty")\n'

>>> f.readline()

''

>>> f.readline()

''

文件也有一个方法为 __next__(), 每次调用就会返回文件的下一行, 应该注意的区别是到达文件末尾 __next__()会引发内置的StopIteration异常, 而不是空字符串

>>> f = open("/Users/mac/Documents/path.py")

>>> f.__next__()

'import sys\n'

>>> f.__next__()

'print(sys.path)\n'

>>> f.__next__()

'print("hello heathty")\n'

>>> f.__next__()

StopIteration

>>>

这个接口就是Python的迭代协议:

1. 有__next__() 方法的对象会前进到下一个结构, 而在末尾会引发StopIteration异常.

2. 在Python中任何这类对象都认为是可迭代的.任何这类对象也能以for循环或者其他迭代工具遍历

3. 所有的迭代工具内部工作都是在每次迭代中调用__next__(), 并且捕捉StopIteration异常来确定何时离开

文件对象有个方法readlines(), 它会在调用时一次把所有的文件加载到内存, 如果文件太大, 以至于计算机内存不够, 甚至不能工作; 而迭代器一次读取一行到内存,可以避免这个问题

>>> for line in open("/Users/mac/Documents/path.py").readlines():

print(line.upper(), end=' ')

IMPORT SYS

PRINT(SYS.PATH)

PRINT("HELLO HEATHTY")

# 迭代器

>>> for line in open("/Users/mac/Documents/path.py"):

print(line.upper(), end=' ')

IMPORT SYS

PRINT(SYS.PATH)

PRINT("HELLO HEATHTY")

手动迭代: iter 和 next

为了支持手动迭代代码, Python3.0提供了内置函数next(), 它会自动调用一个对象的__next__()方法, 调用next(X) 等同于X.__next__(),

>>> f = open("/Users/mac/Documents/path.py")

>>> next(f)

'import sys\n'

>>> next(f)

'print(sys.path)\n'

>>> next(f)

'print("hello heathty")\n'

>>> next(f)

StopIteration

>>>

技术角度来说迭代协议还有一点值得注意. 当for循环开始的时, 会通过for可迭代对象传递给iter内置函数, 以便可迭代对象获取一个迭代器, 返回对象含有__next__()方法.

我们下面看看for循环内部如何处理列表这类内置类型吧

>>> L = [1, 2, 3]

>>> L is iter(L)

False

>>> L.__next__()

AttributeError: 'list' object has no attribute '__next__'

>>> I = iter(L)

>>> I.__next__()

1

>>> I.__next__()

2

>>> I.__next__()

3

>>> I.__next__()

StopIteration

>>>

这一步 I = iter(L) 对于文件来说不是必须的, 因为文件自己就是自己的迭代器, 也就是说文件自己就有__next__()方法, 因此不需要返回一个不同的对象:

>>> f = open("/Users/mac/Documents/path.py")

>>> iter(f) is f

True

>>> f.__next__()

'import sys\n'

>>>

列表以及很多其他内置对象,不是自身的迭代器, 因为它们支持多次打开迭代器, 对这样的对象, 我们必须要iter()内置函数来启动迭代

注意字典中 , 遍历字典的经典方法是明确的获取字典的键的列表; 在Python3.0中, 字典有一个迭代器在迭代环境中,会自动一次返回一个键.

>>> D = dict(a=1, b=2, c=3)

>>> D

{'c': 3, 'b': 2, 'a': 1}

>>> for k in D.keys():print(k)

c

b

a

>>> for k in D:print(k)

c

b

a

>> I = iter(D)

>>> next(I)

'c'

>>> next(I)

'b'

>>> next(I)

'a'

>>> next(I)

StopIteration

>>>

列表解析

列表解析是最常用的迭代协议之一, 经常与for循环一起使用,下面来看看例子

一般修改列表时, 通过遍历列表的元素, 使用range来修改它; 现在有个更加简洁的方法来达到, 我们可以通过产生所需列表的一个单个表达式来替换该循环.

>>> L = [1, 1, 2, 3, 5]

>>> for i in range(len(L)):

L[i] += 2

>>> L

[3, 3, 4, 5, 7]

>>> L = [i + 10 for i in L]

>>> L

[13, 13, 14, 15, 17]

>>>

上述两种方式结果相同, 但是列表解析更加简洁, 并且可能运行更快, 列表解析并不完全和for循环语句版本相同, 因为它会产生一个新的列表对象; 此外列表解析比手动的for循环语句运行更快(大约一倍), 因为他们的迭代在解释器内部是以C语言的速度执行.

列表解析基础知识

L = [i + 10 for i in L]

1. 组成:

列表解析写在一个方括号 [ ]中, 因为它们是最终构建一个新的列表的一种方式;

它以我们组成的一个任意表达式开始, 该表达式使用后面for循环申明的循环变量;

后面的for循环申明循环变量, 以及一个可迭代对象

2. 运行

运行该表达式, Python在解释器内部执行一个遍历L的迭代, 按照顺序把 i 赋值到表达式中, 并且收集表达式的运算结果, 得到一个新列表.

扩展的列表解析语法

作为一个特别有用的扩展, 表达式中嵌套的for循环可以有一个相关的if字句, 用来过滤那些测试结果不为真的项.

>>> L = [4, 5, 7, 9, 12]

>>> [i for i in L if(i%4 ==0)]

[4, 12]

>>>

如果我们需要的话, 列表解析可以更加复杂:

他们可以包含任意嵌套的循环, 也可能被编写为一系列子句.实际上, 他们完整的语法允许任意数目的子句, 每个子句有一个可选的相关if子句

>>> [x+y for x in "ab" for y in "mn"]

['am', 'an', 'bm', 'bn']

其他迭代环境

map:

内置函数, 它把一个函数调用应用于传入的可迭代对象中的每一项,

它有局限性, 因为它需要一个函数,而不是一个任意表达式.

Python3.0中 map返回一个可迭代对象自身, 因此我们需要将它包含到一个list调用已迫使一次性给出所有值

sorted排序可迭代对象的各项;

zip组合可迭代对象的各项;

enumerate根据相对位置匹配可迭代对象的项;

filter选择一个函数为真的项;

reduce针对可迭代对象的成对的项运行一个函数;

range() 内置函数, 返回可迭代对象,

所有这些接受一个可迭代对象, Python3.0中zip,enumerate, filter也像map一样返回一个可迭代对象. 他们都是自己的迭代器----在遍历结果一次之后, 游标就到底了, 没法在此使用__next__()方法了

>>> f = open("/Users/mac/Documents/path.py")

>>> sorted(f)

['import sys\n', 'print("hello heathty")\n', 'print(sys.path)\n']

>>> list(zip(open("/Users/mac/Documents/path.py"), open("/Users/mac/Documents/path.py")))

[('import sys\n', 'import sys\n'), ('print(sys.path)\n', 'print(sys.path)\n'), ('print("hello heathty")\n', 'print("hello heathty")\n')]

>>> list(enumerate(open("/Users/mac/Documents/path.py")))

[(0, 'import sys\n'), (1, 'print(sys.path)\n'), (2, 'print("hello heathty")\n')]

>>>

>>> l = [0, 1, 3]

>>> list(filter(bool, l))

[1, 3]

>>>

>>> import functools ,operator

>>> functools.reduce(operator.add, l)

4

多个迭代器 vs 单个迭代器

range 它不是自己的迭代器(手动迭代, 我们使用iter 产生一个迭代器), 并且它支持器结果上的多个迭代器, 这些迭代器会记住各自的位置:

>>> R = range(3)

>>> R

range(0, 3)

>>> next(R)

TypeError: 'range' object is not an iterator

>>> I1 = iter(R)

>>> next(I1)

0

>>> next(I1)

1

>>> I2 = iter(R)

>>> next(I2)

0

>>>

zip, map, filter不支持相同结果上的多个活跃迭代器

>>> z = zip([1, 2, 3],['a', 'b', 'c'])

>>> list(z)

[(1, 'a'), (2, 'b'), (3, 'c')]

>>> I1 = iter(z)

>>> I2 = iter(z)

>>> next(I1)

StopIteration # 由于上面list(z), 让迭代器的游标知道底部了

>>> z = zip([1, 2, 3],['a', 'b', 'c'])

>>> I1 = iter(z)

>>> I2 = iter(z)

>>> next(I1)

(1, 'a')

>>> next(I1)

(2, 'b')

>>> next(I2)

(3, 'c')

>>> next(I2)

StopIteration

字典视图迭代器

Python3.0中, 字典的keys(), values(), items()方法返回字典视图对象, 他们每次产生一个结果, 而不是在内存中一次产生全部的可迭代对象.

视图保持了和字典中那些项相同的物理顺序, 并且反映底层的字典做出的修改.

下面以keys()方法为例说明, values()与items()与之相同

>>> D = dict(a=1, b=2, c=3)

>>> D

{'b': 2, 'a': 1, 'c': 3}

>>> K = D.keys()

>>> K

dict_keys(['b', 'a', 'c'])

>>> next(K)

TypeError: 'dict_keys' object is not an iterator

>>> I = iter(K)

>>> next(I)

'b'

>>>

python列表迭代器_Python 迭代器之列表解析相关推荐

  1. python列表解析式_Python基础入门-列表解析式

    今天我们使用Python中的列表解析式来实现一些简单功能.好了关于列表解析式是什么?我的理解是它可以根据已有列表,高效创建新列表的方式.列表解析是Python迭代机制的一种应用,它常用于实现创建新的列 ...

  2. python反向迭代器_Python中对象迭代与反迭代的技巧总结

    一.如何实现可迭代对象和迭代器对象? 实际案例 某软件要求从网络抓取各个城市气味信息,并其次显示: 北京: 15 ~ 20 天津: 17 ~ 22 长春: 12 ~ 18 ...... 如果一次抓取所 ...

  3. python函数能返回列表吗_Python函数返回列表还是作为生成器工作?

    我正在尝试创建一个返回对象或作为生成器的函数. 这是一个坏主意,因为作为一种最佳实践,您希望函数可靠地返回相同类型的值,但为了科学的利益-- 我正在使用Python 2,因此range返回一个列表,x ...

  4. python中字典列表元组_Python中的列表和元组

    python中字典列表元组 Lists and tuples are arguably Python's most versatile, useful data types. You will fin ...

  5. python核心数据类型_Python核心数据类型-列表

    Python核心数据类型-列表 关于列表的重要属性 列表是任意对象的有序集合,列表中可以包含任何种类的对象,数字 字符串 或者是其他列表 列表可以通过偏移来读取其中的元素,也可以通过分片读取列表中的某 ...

  6. python取列表中位数_Python如何获取列表(List)的中位数

    前言 中位数是一个可将数值集合划分为相等的上下两部分的一个数值.如果列表数据的个数是奇数,则列表中间那个数据就是列表数据的中位数:如果列表数据的个数是偶数,则列表中间那2个数据的算术平均值就是列表数据 ...

  7. python遍历输出列表元素_python如何遍历列表所有元素?

    方法:首先创建列表("stus = ['孙悟空','猪八戒','蜘蛛精']"),然后通过for循环遍历列表即可("for i in stus:print(i)" ...

  8. python返回列表数据类型_python 数据类型之列表(list)

    一.表达方式 1.英文[]表示 2.列表内部可以存储任意类型的数据 3.可变的有序序列 二.常用函数 1.type():查询变量的类型,如type(["name", "s ...

  9. python 返回列表索引_python怎么返回列表元素索引?

    python中可以使用index()方法返回列表中指定元素的索引. Python index() 方法检测字符串中是否包含子字符串 str ,如果指定 beg(开始) 和 end(结束) 范围,则检查 ...

最新文章

  1. oracle和mysql存储汉字_mysql和oracle的一个汉字占几个字节
  2. 为什么全局变量不好?[翻译]
  3. .Net Core 3.0 IdentityServer4 快速入门02
  4. 为什么说微服务一定要有 API 网关?
  5. WPF中MVVM模式(简略介绍)
  6. Jquery表单与表格的运用
  7. 关于visual studio和vc版本之间的对应关系(更新至2020.07)
  8. 一、如何下载安卓系统源码
  9. 一加3t刷机后还卡_一加3t刷机工具大全+3个ROM
  10. 一级域名是什么?和二级域名有什么区别?
  11. Date setMonth(date.getMonth - 1)
  12. 网线接法简述(直通线、交叉线以及全反线)
  13. 双路服务器 游戏性能,AMD双路128核EPYC跑分无敌 服务器CPU核多才是王道
  14. 《夏风》刊发的几组诗词
  15. 【深度学习】关于EMA:指数移动平均
  16. 人工智能——线性回归(Python实现)
  17. MapStruct系列(6)-映射集合、映射Stream流、映射枚举
  18. 对话架构师:亿级短视频社交「美拍」架构实战
  19. 【WINDOWS / DOS 批处理】for命令详解(四)
  20. SitePoint Podcast#49:Buzz Kill

热门文章

  1. 10个设计最经典的web2.0网站
  2. 【numpy】numpy.where的使用
  3. 个股期权什么意思?场外个股期权又是什么?
  4. 浅谈回车登录的几种方式
  5. 设置canvas的背景成白色
  6. 天涯论坛的经典回帖!!!
  7. 刘芳计算机学院,刘芳,女,1983年生,天津工业大学计算机与软件学院讲师.PDF
  8. 服务器虚拟机配置原则,服务器虚拟机配置
  9. java加密工作模式None_simple1234
  10. 01_我为什么想要成为一名前端工程师