为什么有些对象可以用for … in 循环
我们先看一段代码:
list = [1, 2, 3, 4, 5]
for i in list:
logger.info(i)
这代码定义了1个数组object list, 然后用 for … in 来遍历这个list
看起来合理没什么值得注意
但其实 for … in 后面对象还可以是个String
for i in "hello":
logger.info(i)
还可以是个dict (相当于java 的map)
dict = {
"a": 1, "b": 2}
for key in dict:
logger.info("{}:{}".format(key, dict[key]))
甚至可以是1个文件 open 对象 (TextIOWrapper)
with open("/home/gateman/Documents/jumpserver_installation.log") as f:
for i in f:
logger.info(i)
这样就不是那么能理解了,
for i in loopable_object 这种写法, 用java 的思维来推导 这个loopable_object 一定是实现了某个接口 类似与Loopable
实际上, 这个想法不是全错, 虽然python 没有强接口概念, 但是实际上, python 这个Loopable_object 必须具有 __iter__方法
也就是讲 它必须是1个iterable 对象
iterable 和 iterator 的定义
iterable :
Iterable 的中文意思是可迭代对象, 就是可以被循环的对象, 它在内部必须实现__iter__ 方法
而 iter 方法会返回1个 iterator , 所以实际上iterable 是依赖于它内置的 iterator去迭代元素的
常见的iterable 有List, Dict, String 等等, 所以它们都是可以用for … in … 来循环的
iterator:
上面说了, iterator 中文是迭代器, 它才是真正可以被迭代的对象, 它必须实现__next__ 方法
可以理解为 Iterator 有1个属性 current-item
next 方法会return 当前的current-item
而且会把 current -item 指向 下个item (置于如何找到下个item case by case, 看具体实现)
所以下次调用__next__ 就会返回上一次调用的next item了
而且 iterator 对象也可以用 python built-in 函数next() 来调用
例如
def test_iterator():
list = [1, 2, 3]
iter = list.__iter__()
while True:
try:
print(next(iter))
except StopIteration:
break
上面代码我们多次调用next(iter) 也能实现遍历, 当尝试去获取最后1个元素的next() 对象时,会产生StopIteration Exception
简单归纳下:
真正 可以遍历的东西是 iterator 迭代器, 它必须实现__next__ 接口用于 返回当前的item并改变状态令当前item指向下个
而 iterable 可迭代对象 里面必须实现__iter__ 方法来内置1个iterator
这样iterable 可以被 for … in 来遍历
实际上, 大部分iterator对象, 除了实现__next__方法外, 还实现__Iter__ 方法但让其return 自身