一、迭代器和可迭代对象

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. 利用content为伊特元素追加三个小点
  2. 中关村论坛首次设置技术交易板块,人工智能和新一代信息技术专场发布会即将召开...
  3. php代码审计2全局变量和超全局变量
  4. Excel列数和列字母的转换(column number 和 column letters 互转)
  5. md5和password_hash孰好孰坏
  6. Vmware安装Centos7上网问题的解决
  7. 计算机桌面上的公文包怎么加密,公文包的用法
  8. 手把手教你nginx下如何增加网站
  9. vs没有添加引用_国内考研VS英国读研!各有哪些利弊?
  10. Qt4_使用项视图的简便类
  11. linux 源码安装mysql 5.5
  12. word拼写检查自定义词典下载_取消或开启Word拼写检查和语法(去掉红波浪线)...
  13. UITables With Downloaded Images - Easy Asynchronous Code UITable 异步加载图片
  14. 如何理解Stand SPI Dual SPI 和Quad SPI
  15. sci的figure怎么做_一文看懂SCI论文中都有哪几种Figure
  16. python半自动化获取QQ空间说说
  17. Python 读写文件操作: with open() as f,pickle,pmml,数据库
  18. java pfx 证书_java 证书 .cer 和 .pfx
  19. MongoDB✧SpringDataMongoDB
  20. unity换装骨骼、蒙皮、动作之美

热门文章

  1. ET为什么使用非阻塞IO
  2. 【测试】头脑风暴-01-无接口文档测试推想
  3. 宝藏又小众的威士忌免抠摄影素材网站分享
  4. vue2-ssr从vue-cli搭建项目改造服务端渲染+打包上线部署
  5. word自动编号重新开始于1后缩进不对
  6. 信息检索 度量指标 Normalized Discounted Cumulative Gain NDCG 全
  7. 南京林业大学计算机考研资料,南京林业大学信息科学技术学院884计算机软件基础历年考研真题汇编...
  8. php第三方支付接口视频,接入第三方支付及回调
  9. 愿十月逝去的人,安好
  10. 集团动态丨INTEWELL等产品亮相国资委新技术推介发布会