可迭代对象(Iterable):一个对象只要实现了__iter__()
方法,那么用isinstance()
函数检查就Iterable
对象。
例如:
class IteraObj:
def __iter__(self):
# 这里简单地返回自身
# 但实际情况可能不会这么写
# 而是通过内置的可迭代对象来实现
# 下文的列子中将会展示
return self
it = IterObj()
print(isinstance(it, Iterable)) # true
print(isinstance(it, Iterator)) # false
print(isinstance(it, Generator)) # false
常见的可迭代对象:
list
, tuple
, set
, dict
, str
;__iter__()
方法的对象;自定义的
Iterable
对象,要满足在for
循环中正确使用,必须保证__iter__()
方法正确实现(可以通过内置iter()
函数将其转换成Iterator
对象)。
__getiem__()
方法的对象,可以通过 iter()
函数转化成 Iterator
对象。即 一个对象能够在 for
循环中运行, 但不一定是Iterable
对象。首先验证1,2
具体如下:
# 1.
from collections import Iterable, Iterator
print(isinstance([], Iterable)) # true list是可迭代的
print(isinstance({}, Iterable)) # true dict是可迭代的
print(isinstance((), Iterable)) # true tuple是可迭代的
print(isinstance(set(), Iterable)) # true set是可迭代的
print(isinstance('', Iterable)) # true str是可迭代的
print(isinstance([], Iterator)) # False
print(isinstance({}, Iterator)) # False
print(isinstance((), Iterator)) # False
print(isinstance(set(), Iterator)) # False
print(isinstance('', Iterator)) # False
# 2.
cur_path = os.path.dirname(os.path.abspath(__file__))
with open(cur_path + '/model.py') as f:
print(isinstance(f, Iterable)) # true
print(isinstance(f, Iterator)) # true
# 3.
print(hasattr([], '__iter__')) # true
print(hasattr({}, '__iter__')) # true
print(hasattr((), '__iter__')) # true
print(hasattr('', '__iter__')) # true
结论:集合和序列对象是可迭代的但不是迭代器。
这些内置集合或序列对象都含有 __iter__
属性,是Iterable
对象。但它们要在 for
循环中被使用,就应该能够被内置的 iter()
函数调用并转化成 Iterator
对象。
例如:
print(iter([])) #
print(iter({})) #
print(iter(())) #
print(iter('')) #
这些内置集合或序列为Iterable
对象, 都可以转换为对应的 Iterator
对象。
其次验证3
再回头修改自定的 IterObj
类
class IterObj:
def __init__(self):
self.a = [3, 5, 7, 11, 13, 17, 19]
def __iter__(self):
return iter(self.a)
it = IterObj()
print(isinstance(it, Iterable)) # true
print(isinstance(it, Iterator)) # false
print(isinstance(it, Generator)) # false
print(iter(it)) #
for i in it:
print(i) # 将打印3、5、7、11、13、17、19元素
结论:在定义一个Iterable
对象是,要注意__iter__()
方法的内部实现逻辑, 一般情况下,利用一些已知的 Iterable
对象(如集合、序列、文件等或其他正确定义的Iterable
对象)来辅助我们实现。
最后验证4
iter()
函数可以将一个实现了 __getitem__()
方法的对象转换成Iterator
对象,但他不是 Iterable
对象。
例子:
class IterObj:
def __init__(self):
self.a = [3, 5, 7, 11, 13, 17, 19]
def __getitem__(self, i):
return self.a[i]
it = IterObj()
print(isinstance(it, Iterable)) # false
print(isinstance(it, Iterator)) # false
print(isinstance(it, Generator)) false
print(hasattr(it, "__iter__")) # false
print(iter(it)) #
for i in it:
print(i) # 将打印出3、5、7、11、13、17、19
结论:可以在 for 中使用的对象,不一定是可迭代对象。
综上所述
Iterable
对象是实现了 __iter__()
方法的对象;for
中循环使用,就必须满足 iter()
的调用(即调用这个函数不会出错,能正确转成一个 Iterator
对象)Iterable
对象来辅助实现我们自定义的Iterable
对象。__getiem__()
方法, 可以通过 iter()
函数转换成 Iterator
对象,即可以在 for
循环中使用,但它不是一个Iterable
对象。定义: 一个对象实现__iter__()
和__next__()
两个方法,那么它就是一个Iterator
对象。
作用: 遍历集合元素。注意:只能从开头顺序访问至结尾。
特点:
iter()
和next()
。iter()
方法构建迭代器。form collections import Iterable, Iterator
l = [1,2,3,4,5]
print(isinstance(l, Iterable)) # True 可迭代对象
print(isinstance(l, Iterator)) # False 不是迭代器
it = iter(l) # 创建迭代器对象
print(isinstance(it, Iterable)) # True 可迭代对象
print(isinstance(it, Iterator)) # False 不是迭代器
# 1. next() 顺序遍历迭代器
print(next(it), end=" ")
#2. for() 循环遍历迭代器
for x in it:
print(x)
__iter__()
方法 → 起始位置__next__()
方法 → 下一个,终止位置from collections import Iterable, Iterator
# 构建一个可以反向输出的列表可迭代对象
class listDemo(object):
def __init__(self):
self.__data = []
self.__num = 0
def __iter__(self):
return self
def __next__(self):
if self.__num <= 0:
raise StopIteration # 终止
else:
self.__num -= 1
return self.__data[self.__num]
def __setitem__(self, key, value): # 插入
self.__data.insert(key, value)
self.__num += 1
def __getitem__(self, index): # 读取
return self.__data[index]
def __delitem__(self, index): # 删除
del self.__data[index]
self.__num -= 1
def __len__(self):
return len(self.__data)
mylist = listDemo()
mylist[0], mylist[1], mylist[2], mylist[3] = '1', '2', '3', '4'
print('Iterable:', isinstance(mylist, Iterable))
print('Iterator:', isinstance(mylist, Iterator))
# 法1: 无需iter(), 因为该对象已为迭代器对象
print(next(mylist))
print(next(mylist))
# 法2: 从当前迭代器位置 for循环
for i in mylist:
print(i, end=" ")
del mylist[2]
print(len(mylist))
print(type(mylist))
斐波那契迭代器
相关知识
class Fibonacci(): # 定义迭代器类
def __init__(self):
self.a = 0
self.b = 1
def __iter__(self):
return self
def __next__(self):
if self.b > 100:
raise StopIteration # 结束条件
else:
self.a, self.b = self.b, self.a + self.b
return self.a
fib = Fibonacci() # 实例化迭代器对象
# for 循环
for f in fib:
print(f, end=' ')
方式:
特点:
一个生成器对象既是可迭代对象,也是迭代器对象。
验证方式1
from collections import Iterator, Iterable, Generator
g = (x * 2 for x in range(10)) # 0~18的偶数生成器
print(isinstance(g, Iterable)) # true
print(isinstance(g, Iterator)) # true
print(isinstance(g, Generator)) # true
print(hasattr(g, "__iter__")) # true
print(hasattr(g, "__next__")) # true
print(next(g)) # 0
print(next(g)) # 2
for x in g:
print(x, end=' ')
验证方式2
yield
的作用相当于return
,可通过next()
函数或for
循环遍历。yield
关键字,生成函数返回当前值,继续向下执行。def gen():
for i in range(5):
print('before')
yield i # 生成器函数
print('after')
print('end')
it = gen()
print(list(it)) # 直接将生成器能生成的所有值存储成列表或者元组的形式
it2 = gen()
print(next(it2))
print(it2.__next__())
it3 = gen()
for i in it3:
print(i, end=" ")
Python容器
一文彻底搞懂Python可迭代(Iterable)、迭代器(Iterator)和生成器(Generator)的概念