01-字符串内容补充
1. 何为迭代?
点击展开阅读
在学习 Python 时,我们经常会听到 “可迭代”(iterable) 这个词。对于初学者来说,这个概念可能有些抽象。那么,什么是“可迭代”?它和“不可迭代”有什么区别?今天我们就用通俗易懂的方式来讲解这个概念,让你一看就懂!这部分的知识,也是为了便于后续的学习而增加的。
用一个类似的知识来辅助下面知识点的理解:分子属于可迭代对象,原子属于不可迭代对象。为什么这么说呢:分子可以拆分成原子,但原子属于不可再拆分。可以再被拆分的称为可迭代,不可再被拆分的称为不可迭代。
1. 什么是:“可迭代”?
在 Python 编程中,“可迭代”(iterable)是指 可以一个一个取出元素的东西。
1.1 举个简单的例子
想象你有一本书,书里有很多页。你可以一页一页地翻,这本书就是可迭代的,因为你可以“遍历”它的每一页。
再比如:想象你有一个音乐播放列表,里面有很多歌曲,你可以一首一首地播放。这个播放列表就是可迭代的,因为你可以逐个获取里面的每一首歌,并且按顺序播放或随机播放。
在 Python 中,可迭代的对象包括:
对象类型 | 示例代码 | 说明 |
---|---|---|
列表(list) | ["苹果", "香蕉", "橙子"] | 有序、可变,适合存储多个元素 |
元组(tuple) | ("猫", "狗", "兔子") | 有序、不可变,适合存储多个固定值 |
字符串(str) | "Hello Bornforthis.cn" | 由字符组成,可以逐个遍历 |
字典(dict) | {"name": "Bornforthis", "age": 20} | 由键值对组成,可迭代键、值或项 |
集合(set) | {"红色", "蓝色", "绿色"} | 无序、唯一元素集合 |
文件对象(file) | open("test.txt") | 可以逐行读取内容(也就是可以一行一行读取) |
1.2 可迭代小结
如果一个东西可以一个一个取出元素,并且能被 for
循环使用,那它就是 可迭代的(iterable)。这在 Python 编程中很重要,因为很多操作都依赖于可迭代对象,比如 for
循环、列表推导式、map()
、filter()
等等。
你可以把“可迭代”理解成 可以按顺序拿出来用的东西,这样就容易理解了!
1.3 代码示例(选看)
你有可能会想:为什么代码要放在这个部分,而不是放在例子下面?——因为,这部分代码涉及的 for 循环语法还未讲解,但觉得还是放一下,方便读者阅读理解。这部分的代码阅读准则如下:
- 你直接看的懂的话,那就没事;
- 如果你无法直接看懂,那么直接大概看一下,可以理解可迭代的含义即可,不用也不要深究代码原理或语法,后面都会讲解的!
在 Python 里,播放列表就像是一个列表(list):
playlist = ["歌曲1:你眼中的星辰", "歌曲2:灵眸", "歌曲3:花式篮球(少年版)"]
for song in playlist:
print(f"正在播放{song}")
📌 输出:
正在播放歌曲1:你眼中的星辰
正在播放歌曲2:灵眸
正在播放歌曲3:花式篮球(少年版)
2. 什么是“不可迭代”的对象?
在 Python 中“不可迭代”的(non-iterable)的是指不可被拆分,也就是不可以一个一个取出元素的东西。
不可迭代对象(Non-iterable)是指不可被拆分,不能一个一个取出元素,不能用 for
循环遍历的对象。
2.1 举个简单的例子:
不可迭代(non-iterable) 的对象指的是不能一个一个取出元素。想象你有一块石头,这块石头是不可迭代的。你不能像翻书一样,从石头里一块一块地取出“页”来读,因为它是一个整体,没有分成多个可以依次取出的部分。
再比如:想象你有一杯水,这杯水是不可迭代的。你不能像数硬币一样,一枚一枚地取出水滴,因为水是一个整体,无法被逐个“遍历”出来。
在 Python 中,以下几类对象通常是不可迭代的:
对象类型 | 示例 | 是否可迭代? | 原因 |
---|---|---|---|
整数(int) | 123 | ❌ 不是 | 不是一组元素,无法逐个取出 |
浮点数(float) | 3.14 | ❌ 不是 | 不能遍历其中的内容 |
布尔值(bool) | True 、False | ❌ 不是 | 只有两个值,不能逐个取出 |
None值(NoneType) | None | ❌ 不是 | 代表“无”,没有元素可遍历 |
📌 记住:不可迭代的对象通常是单个数据,而不是一组元素! 💡
2.2 不可迭代小结
如果一个东西不能一个一个取出元素,也不能被 for
循环遍历,那它就是 不可迭代的(non-iterable)。虽然不可迭代对象不能用于 for
循环,但它们在编程中依然非常重要,主要用于存储和计算单个值,以及控制程序逻辑。
2.3 代码示例(选看)
这里和前面可迭代的要求一样,只求理解不可迭代的含义即可。
# 尝试对不可迭代的对象使用 for 循环
non_iterable = 1
for item in non_iterable:
print(item) # ❌ TypeError: 'int' object is not iterable
为什么会报错?——1
是整数,它本身不是一组元素,你可以把这个 1 再拆开吗?显然是不能继续拆开的。(如果此时有杠精的话,请告诉我你可以把 1 拆解成什么?)不能被 for
逐个遍历,所以是不可迭代的。
3. 补充
3.1 使用代码辨别是否可迭代
前面讲了什么是可迭代、不可迭代,并且给你列举了在 Python 当中哪些是否可以迭代的表格。有些读者阅读之后,怕自己判断不正确或各种原因,我提供一个代码来辅助判断是否数据可迭代。
方法一:使用
collections.abc.Iterable
Python 提供了
collections.abc.Iterable
作为判断是否可迭代的基类,可以用isinstance()
来检查:from collections.abc import Iterable print(isinstance([1, 2, 3], Iterable)) # ✅ True,列表是可迭代的 print(isinstance("hello", Iterable)) # ✅ True,字符串是可迭代的 print(isinstance(100, Iterable)) # ❌ False,整数不是可迭代的 print(isinstance(3.14, Iterable)) # ❌ False,浮点数不是可迭代的
优点:推荐的 Pythonic 方式,符合 Python 的面向对象原则。
方法二:使用
iter()
函数Python 的
iter()
内置函数会尝试获取对象的迭代器。如果对象可迭代,则iter()
不会报错,不可迭代则报错:print(iter([1, 2, 3])) # ✅ 正常返回一个迭代器 print(iter(100)) # ❌ TypeError: 'int' object is not iterable
优点:直接测试对象是否实现了
__iter__()
或__getitem__()
方法。方法三:使用
type()
检查如果你只想检查常见的可迭代类型(如
list
,tuple
,set
,dict
,str
,range
),等于说是提前把可迭代的类型放进元组,然后使用 in 来判断检测的类型是否存在目标可迭代元组中。print(type([1, 2, 3]) in (list, tuple, set, dict, str, range)) # True print(type(123) in (list, tuple, set, dict, str, range)) # False print(type("hello") in (list, tuple, set, dict, str, range)) # True print(type({1, 2, 3}) in (list, tuple, set, dict, str, range)) # True print(type(range(10)) in (list, tuple, set, dict, str, range)) # True
缺点:这种方法只能判断有限的内置类型,不能检测自定义的可迭代对象。
方法四:检查
__iter__()
或__getitem__()
方法Python 的迭代协议要求对象实现
__iter__()
方法,或者对于旧式迭代器,实现__getitem__()
方法:def is_iterable(obj): return hasattr(obj, '__iter__') or hasattr(obj, '__getitem__') print(is_iterable([1, 2, 3])) # True print(is_iterable(123)) # False print(is_iterable("hello")) # True
优点:简单直接,适合了解对象的内部机制。
方法五:使用
dir()
检查可以通过
dir()
方法查看对象的方法列表:def is_iterable(obj): return '__iter__' in dir(obj) or '__getitem__' in dir(obj) print(is_iterable([1, 2, 3])) # True print(is_iterable(123)) # False print(is_iterable("hello")) # True
优点:类似
hasattr()
,但dir()
返回的内容更丰富,适合调试时使用。
其实,是否可以 for 循环也是判断是否可迭代的方法。 这里就不给演示代码了,前面我也提供了。可以循环的不会报错,不可以循环的会报错。
至于如果你想要问我要一个准确答案:推荐使用哪种方法来实现呢?这里我可以明确的告诉你,没有什么推荐不推荐。上面每种方法的大致好坏我都写出来了。但是具体实际使用的时候怎么选呢?我给你下面几个原则:
- 原则一:按你自己对上面几种检测方法的理解来使用,也就是你从我提供的代码中,产生的属于自己的总结(理解)来使用;
- 原则二:按具体场景来使用,其实也就是按需求来选择;
- 原则三:原则三你用不到,如果你还是想要一个老师提供的结论,那么请你不用学了。开玩笑的,你可以选择使用上面的方法三,因为当你能用到原则三时,表面你没有产生属于自己的思考和理解,也没有按照具体的需求来使用。
对于上面的方法四、方法五,你不理解也没事。我为了本书的完整性,都提供一下。便于以后你达到 Python 某种水平时,本书依然适配,依然是你的选择足矣。
3.2 更多实际例子辅助理解
在写本章节中,我想了许多例子,但是刚刚要着笔写又觉得例子有漏洞,或许是私教学生带的比较多,所以考虑的比较全面。鉴于每个读者年龄段和理解不一样,我多举几个不同的不可迭代的例子。以便让你真正理解,这个部分的知识点。
这里有 10 个贴切的可迭代 VS. 不可迭代对象的类比,方便理解什么是迭代和不可迭代的:
灯泡 💡
- 可迭代的对象像是一串圣诞彩灯,你可以一个一个地数出灯泡。
- 不可迭代的灯泡是单个整体,无法一个一个地拆开来看。
鸡蛋 🥚
- 可迭代的对象像是一盒鸡蛋,你可以一个一个取出。
- 单个鸡蛋是整体,不能像一盒鸡蛋那样“遍历”它。
足球 ⚽
- 可迭代的对象像是一筐足球,你可以一个个拿出来。
- 单个足球是整体,不能一个个拆开来取出“元素”。
硬币 🪙
- 可迭代的对象像是一堆硬币,你可以逐个数出来。
- 一枚硬币本身是不可迭代的,不能拆成多个部分来遍历。
水滴 💧
- 可迭代的对象像是一场小雨,每一滴雨水都可以单独感受到。
- 一滴水是一个整体,无法像一场小雨那样“遍历”它。
砖块 🧱
- 可迭代的对象像是一堵砖墙,每块砖都能单独拆出来。
- 单块砖本身是整体,不能被拆成多个元素来遍历。
篮球🏀
- 可迭代的对象像是一筐篮球,你可以一个个拿出来。
- 单个篮球本身是一个完整的东西,不能逐个取出“部分”来看。
杯子 ☕
- 可迭代的对象像是一排杯子,你可以逐个数出每个杯子。
- 单个杯子是整体,不能像一排杯子那样被“遍历”。
苹果🍏
- 可迭代的对象像是一篮子苹果,你可以一个个取出。
- 单个苹果本身是完整的,不能像一篮子苹果那样“遍历”它的内容。
网球拍🎾
可迭代的对象像是一堆网球拍,你可以一个一个拿出来。
单个网球拍是整体,不能像一堆网球拍那样“逐个遍历”它的元素。
数字🔢
- 可迭代的是一组数字,比如你手里有一个竹筐,里面放了一筐幼儿园的立体数字,放了:
1,2,3,4,5,6,7,8,9
,你可以一个一个取出竹筐中的立体数字。 - 不可迭代的是一个具体的立体数字,比如 1(你不能逐个取出它的“元素”)。
- 可迭代的是一组数字,比如你手里有一个竹筐,里面放了一筐幼儿园的立体数字,放了:
音乐专辑/音乐播放列表💽
- 可迭代的是专辑中的每首歌曲,你可以一首一首的播放。
- 不可迭代的是一首独立的歌曲(你不能遍历它的不同部分,除非它是一个字符串)
购物清单🧾
- 可迭代的是购物清单上面的每个商品条目。
- 不可迭代的是清单本身,清单本身已经不能被再拆分。
总结:
- “可迭代” = 可以一个一个取出来的东西(比如一盒鸡蛋、一堆硬币)。
- “不可迭代” = 是一个完整的个体,无法拆分遍历(比如单个鸡蛋、一枚硬币)。
这样对比理解是不是更清晰了呢?多思考,多理解,这很重要。
4. 记住这个简单的规则!
能 for
循环的,就是可迭代的;不能 for
循环的,就是不可迭代的! 💡
总之,虽然有重复论述之嫌。但还是要再提一次:可迭代的对象就像一个“可以一个个取出来用的集合”,而不可迭代的对象通常是单个独立的东西。
未来便于你随时查阅,我制作了如下表格:
对象类型 | 可迭代? | 原因 |
---|---|---|
list (列表) | ✅ 是 | 包含多个元素,可以逐个取出 |
tuple (元组) | ✅ 是 | 和列表类似 |
str (字符串) | ✅ 是 | 由字符组成,可以逐个取出 |
dict (字典) | ✅ 是 | 键或值可以逐个取出 |
set (集合) | ✅ 是 | 包含多个元素 |
file (文件对象) | ✅ 是 | 可以逐行读取 |
int (整数) | ❌ 不是 | 不是一组元素,无法逐个取出 |
float (浮点数) | ❌ 不是 | 不能遍历其中的内容 |
bool (布尔值) | ❌ 不是 | 只有 True /False ,无元素可取 |
更新日志
475af
-于61ab5
-于aa5ec
-于28174
-于bd51e
-于94a7c
-于3f9a7
-于9ab1e
-于16604
-于1c35a
-于789bb
-于862f2
-于bb83b
-于d9f4a
-于23be2
-于768b0
-于0ab0d
-于1e79b
-于20103
-于92102
-于d9da1
-于3c69a
-于310d1
-于1f4e0
-于