一、迭代器和可迭代对象

1.1 哪些是可迭代对象?如何检测?

只要能用for x in X进行迭代的对象,都叫可迭代对象;检测一个对象是否是可迭代对象,可以用isinstace(seq, Iterable)语句,其中 Iterable类型在collections模块中,需要手动导入。

1.2 常见的可迭代对象、迭代器有哪些?

常见的可迭代对象,包括list, tuple, set, dict, ndarray等。

常见的迭代器,比如文件句柄对象,open()函数的返回值就是迭代器。

1.3 可迭代对象和迭代器的区别

可迭代对象不一定是迭代器,但是迭代器一定是可迭代对象;因此迭代器中包括可迭代对象没有的属性和方法,比如__next__(),这也导致迭代器可以传入next()而可迭代对象不行。

可迭代对象在遍历时不会发生消耗,但是迭代器是会发生消耗的;这句话很重要,是本文重点,也是全网文章中很少讲到的一个点。

二、对1.3中重点语句的进一步实验

2.1 文件对象中的read()、readline()、readlines()

本节主要参考以前我写的一篇文章。

先创建一个txt文件,一共有5行。

当先将第一行的内容传给line后,打印出line,然后再直接用read()读完所有内容,下一次直接没办法迭代。

with open('123.txt', 'r') as f:for line in f:print(line)print(f.read())print('Loop Ending.')# ugyiqvqivew# asaass
# sadasfa
# ggtrhtr
# adxzch
# Loop Ending.

而如果把read()注释掉,那么就会迭代5次,分别对应每一行。

with open('123.txt', 'r') as f:for line in f:print(line)# print(f.read())print('Loop Ending.')# ugyiqvqivew# Loop Ending.
# asaass# Loop Ending.
# sadasfa# Loop Ending.
# ggtrhtr# Loop Ending.
# adxzch
# Loop Ending.

本节的结论:对于迭代器——文件句柄对象,我们可用for x in X来遍历它,每一次的遍历都会导致内容的消耗,当然也可以用read()、readline()、readlines()来遍历其中的内容。

2.2 对于迭代器,普遍可以用iter()、for x in X、islice()等方法遍历

上一节讲的是迭代器中的文件句柄对象可以用read()、readline()、readlines()来遍历;那么对于迭代器,普遍存在哪些方式去遍历其中内容呢?

2.2.1 循环遍历法——for x in X

list1 = [1,2,3,4,5,6]it = iter(list1)for i in it:print(i)if i == 3:print(list(it))  # list函数会遍历完迭代器所有元素# 1
# 2
# 3
# [4, 5, 6]

2.2.2 下一个遍历法——next()

list1 = [1,2,3,4,5,6]it = iter(list1)# next函数仅仅遍历迭代器的一个元素,调用一次消耗一次
print(next(it))  # 1
print(next(it))  # 2
print(next(it))  # 3print(list(it))  # [4, 5, 6]print(next(it))  # 因为上面已经遍历完了,所以再遍历就会出异常;Exception : StopIteration 

2.2.3 转换遍历法——list()、tuple()、set()、deque()、dict()

(1)转换成列表——list()

list1 = [1,2,3,4,5,6]it = iter(list1)for i in it:print(i)if i == 3:print(list(it))  # list函数会遍历完迭代器所有元素# 1
# 2
# 3
# [4, 5, 6]

(2)转换成元组——tuple()

list1 = [1,2,3,4,5,6]it = iter(list1)for i in it:print(i)if i == 3:print(tuple(it))  # tuple函数会遍历完迭代器所有元素# 1
# 2
# 3
# (4, 5, 6)

(3)转换成集合——set()

list1 = [1,2,3,4,5,6]it = iter(list1)for i in it:print(i)if i == 3:print(set(it))  # set函数会遍历完迭代器所有元素# 1
# 2
# 3
# {4, 5, 6}

(4)转换成队列——deque()

import collectionslist1 = [1,2,3,4,5,6]it = iter(list1)for i in it:print(i)if i == 3:print(collections.deque(it))  # deque函数会遍历完迭代器所有元素# 1
# 2
# 3
# deque([4, 5, 6])

(5)转换成字典——dict()

list1 = [('a',1), ('b',2), ('c',3), ('d',4)]it = iter(list1)for i,t in enumerate(it):print(t)if i == 1:print(dict(it))  # dict函数会遍历完迭代器所有元素# ('a', 1)
# ('b', 2)
# {'c': 3, 'd': 4}

2.2.4 切片遍历法——islice()

from collections import deque
import itertools
import numpy as npiterable = [40,30,50,46,39,44,45,67,89,34]
it = iter(iterable)
print(itertools.islice(it, None, 5, 2))  # 不用变量接收时,仅用print()无法完成遍历
print(list(it))  # [40, 30, 50, 46, 39, 44, 45, 67, 89, 34] ,因此输出的内容保留不变iterable = [40,30,50,46,39,44,45,67,89,34]
it = iter(iterable)
print(list(itertools.islice(it, None, 5, 2)))  # 不用变量接收时,但是用list完成了islice对象的遍历
print(list(it))  # [44, 45, 67, 89, 34] ,因此输出内容有所消耗iterable = [40,30,50,46,39,44,45,67,89,34]
it = iter(iterable)
print(tuple(itertools.islice(it, None, 5, 2)))  # 不用变量接收时,但是用tuple完成了islice对象的遍历
print(list(it))  # [44, 45, 67, 89, 34] ,因此输出内容有所消耗iterable = [40,30,50,46,39,44,45,67,89,34]
it = iter(iterable)
print(set(itertools.islice(it, None, 5, 2)))  # 不用变量接收时,但是用set完成了islice对象的遍历
print(list(it))  # [44, 45, 67, 89, 34] ,因此输出内容有所消耗iterable = [('a',40), ('b',30), ('c',50), ('d',46)]
it = iter(iterable)
print(dict(itertools.islice(it, None, 5, 2)))  # 不用变量接收时,但是用dict完成了islice对象的遍历
print(list(it))  # [] ,因此输出内容有所消耗iterable = [40,30,50,46,39,44,45,67,89,34]
it = iter(iterable)
print(deque(itertools.islice(it, None, 5, 2)))  # 不用变量接收时,但是用deque完成了islice对象的遍历
print(list(it))  # [44, 45, 67, 89, 34]# <itertools.islice object at 0x0000022F09409EA0>
# [40, 30, 50, 46, 39, 44, 45, 67, 89, 34]
# [40, 50, 39]
# [44, 45, 67, 89, 34]
# (40, 50, 39)
# [44, 45, 67, 89, 34]
# {40, 50, 39}
# [44, 45, 67, 89, 34]
# {'a': 40, 'c': 50}
# []
# deque([40, 50, 39])
# [44, 45, 67, 89, 34]

切片遍历法有两种实施方式,要么直接转,要么先传给一个中间变量再转;前者在上面这一块代码,后者具体看下面的这块代码。

import itertools# 情况1:start和stop都不是None,则在区间内的元素才被消耗
iterable = [40,30,50,46,39,44,45,67,89,34]
it = iter(iterable)
d = itertools.islice(it, 2, 4)
print(list(d))   # [50, 46]
print(list(it))  # [39, 44, 45, 67, 89, 34]# 情况2:stop是None,则所有元素都被消耗
iterable = [40,30,50,46,39,44,45,67,89,34]
it = iter(iterable)
d = itertools.islice(it, 4, None, 2)
print(list(d))
print(list(it))  # []# 情况3:start是None,则从一开头到stop区间中的元素被消耗
iterable = [40,30,50,46,39,44,45,67,89,34]
it = iter(iterable)
d = itertools.islice(it, None, 5, 2)
print(list(d))   # [40, 50, 39]
print(list(it))  # [44, 45, 67, 89, 34]# [50, 46]
# [39, 44, 45, 67, 89, 34]
# [39, 45, 89]
# []
# [40, 50, 39]
# [44, 45, 67, 89, 34]

对于切片遍历法消耗内容的范围;如果stop设置为None,那么会遍历(消耗)所有元素;而如果start没设置为None,start往前的元素并不会被遍历(消耗)到。 详见上面的代码块。

2.3 哪些方法看起来能遍历但实际无法遍历?

2.3.1 print(iterator)函数无法遍历

list1 = [1,2,3,4,5,6]it = iter(list1)for i in it:print(i)# 1
# 2
# 3
# 4
# 5
# 6

2.3.2 numpy.array()或numpy.asarray()函数并无法遍历迭代器中的内容

import numpy as nplist1 = [1,2,3,4,5,6]it = iter(list1)for i in it:print(i)if i == 3:print(np.array(it))  # 返回的结果和不用np.array()的一样# 1
# 2
# 3
# <list_iterator object at 0x0000022F08FA78E0>
# 4
# 5
# 6

python-哪些是可迭代对象?哪些是迭代器?迭代器和可迭代对象的区别——可迭代对象在遍历时不会发生消耗,但是迭代器会相关推荐

  1. Python基础知识——函数的基本使用、函数的参数、名称空间与作用域、函数对象与闭包、 装饰器、迭代器、生成器与yield、函数递归、面向过程与函数式(map、reduce、filter)

    文章目录 1 函数的基本使用 一 引入 二 定义函数 三 调用函数与函数返回值 2 函数的参数 一 形参与实参介绍 二 形参与实参的具体使用 2.1 位置参数 2.2 关键字参数 2.3 默认参数 2 ...

  2. 经典 Python参数传递采用的肯定是“传对象引用”的方式。相当于传值和传引用的一种综合。如果函数收到的是一个可变对象(比如字典或者列表)的引用,就能修改对象的原始值--相当于通过“传引用”来传递对象

    python不允许程序员选择采用传值还是传引用.Python参数传递采用的肯定是"传对象引用"的方式.这种方式相当于传值和传引用的一种综合.如果函数收到的是一个可变对象(比如字典或 ...

  3. python对象属性是与数据有关的项目_python之对象产生,属性(定义的值)的查找原则,对象绑定关系...

    例1:                                 通过外部定义一个函数也可以传值进去 class OldboyStudent: school='oldboy' def choos ...

  4. java让对象分配在栈上_java – Hotspot何时可以在堆栈上分配对象?

    我做了一些实验,以便了解Hotspot何时可以进行堆栈分配.事实证明,它的堆栈分配比基于available documentation的预期要有限得多.Choi"Escape Analysi ...

  5. 怎么确定迭代器后面还有至少两个值_学会迭代和迭代器,让你的程序更省内存...

    迭代,很熟悉有很陌生,猛地一说,好多人摸不到头脑,但是在编程语言中,是常见的一种说法.今天我们就走进迭代,讲述一下迭代以及迭代器的用法. 迭代定义:通过for 循环遍历列表,元组,我们就称之为迭代! ...

  6. python中readlines是什么意思_python中read、readline、readlines之间的区别

    读写文件是最常见的IO操作.Python内置了读写文件的函数,用法和C是兼容的.读写文件前,我们先必须了解一下,在磁盘上读写文件的功能都是由操作系统提供的,现代操作系统不允许普通的程序直接操作磁盘,所 ...

  7. python---面向对象,class参数、__init__方法、与函数区别

    python-面向对象,class简介 进阶 面向对象第一节 初识class1.如何去定义一个最基本的class 2.class最基本的子元素 3.class传参 4.__init__方法 5.cla ...

  8. 块存储、文件存储、对象存储这三者和分布式文件存储系统的本质区别

    块存储和文件存储是我们比较熟悉的两种主流的存储类型,而对象存储(Object-based Storage)是一种新的网络存储架构,基于对象存储技术的设备就是对象存储设备(Object-based St ...

  9. SQLServer错误:过程 sp_addextendedproperty,第 xxx 行对象无效。'dbo.xxx.xxx' 不允许有扩展属性,或对象不存在。...

    上传数据库到虚拟主机,在执行SQL脚本的时候出现以下的错误: 消息 15135,级别 16,状态 8,过程 sp_addextendedproperty,第 37 行 对象无效.'dbo.Messag ...

最新文章

  1. 亲君圆梦,创业一起来
  2. vs2013突然没有代码提示功能了。
  3. 用Python玩转微信的正确姿势!
  4. excel函数公式html文档,Excel中把计算式转换为运算结果的方法 EXCEL中计算出的公式如何转换成纯文本内容?...
  5. 《推荐系统实践》样章:如何利用用户标签数据
  6. 人受失败后多久可以做第二次_做完皮秒多久可以用自己的护肤产品、过来人分享皮秒后怎么护肤?...
  7. 最小二乘法的几何意义
  8. 网盘上传文件服务器失败原因,win10系统在百度网盘上传文件一直失败的恢复教程...
  9. #腾讯云·未来开发者云梯计划#第三期上线啦!全国5000个免费云认证培训考试名额开放报名中!
  10. 教你一键开发桌面应用程序
  11. 厉害了!北大3位硕博生搞出ChatGPT版Excel!动动嘴就能自动处理表格……免费用!...
  12. 字节跳动2020届秋招笔试题
  13. 泰坦尼克号生存预测(超详细)
  14. 【google】解决google浏览器不弹出账号密码保存框且无法保存登录信息问题
  15. 华为设备流量抑制及风暴控制配置命令
  16. 用 CodeRuler 征服中世纪王国
  17. SAP 项目实施阶段全过程
  18. GD32F103C读写flash
  19. OpenStack floating IP
  20. Android开发之歪门邪道给 文本选中追加第三方软件入口

热门文章

  1. phantomjs 中文文档
  2. IBM Notes 901FP10IF6发布
  3. XP系统不识别2t以下硬盘的解决方法
  4. 冈萨雷斯DIP第4章知识点
  5. binlog2sql恢复mysql数据
  6. 东北林业大学第15届校赛(大二组) 题解
  7. 《傅雷家书》-文摘三-修养
  8. forEach循环中异步操作的问题
  9. 入手联想G460有感
  10. 神奇的伽玛函数(上)