可迭代对象
可迭代对象可以使用for循环遍历取值, 比如:列表、元组、字典、集合、range、字符串。
可迭代对象必须实现__iter__()魔法函数
from collections.abc import Iterable
print(isinstance([],Iterable)) # 判断列表是否是可迭代对象
print(isinstance((),Iterable)) # 判断元组
print(isinstance({},Iterable)) # 判断集合
print(isinstance("hello world",Iterable)) #判断字符串
print(isinstance(100,Iterable))
迭代器
迭代器对象,必须要实现__next__()魔法函数。
list、tuple等都是可迭代对象,可以通过iter()函数获取这些可迭代对象的迭代器。然后我们可以对获取到的迭代器不断使用next()函数来获取下一条数据。iter()函数实际上就是调用了可迭代对象的 iter 方法。next()实际调用了迭代器的__next__()方法
获取字符串的迭代对象
from collections.abc import Iterator
# 将字符串创建迭代器对象
str1 = "hello world"
iter1 = iter(str1) # 使用iter()函数获取迭代器对象
print(type(str1))
print(type(iter1)) # type()返回变量的类型
获取列表的迭代对象
# 将list对象创建迭代器
list1 = [1, 2, 3, 4, 5]
iter1 = iter(list1)
print(next(iter1)) # 输出1
print(iter1.__next__()) # 和上一行效果相同, 输出2
for i in iter1:
print(i)
print(isinstance(iter1,Iterator)) # 判断是否是迭代器类型
# 将tuple对象创建迭代器
tuple1 = (1, 2, 3, 4, 5)
iter3 = iter(list1)
#使用for循环遍历迭代器
for i in iter3:
print(i)
# 利用next遍历迭代对象
while True:
try:
print(next(iter1))
except StopIteration:
break
自定义可迭代对象
# 定义可迭代对象
class TestIterable:
def __init__(self,x):
self.x = x
def __iter__(self): # 可迭代对象必须实现此方法
return iter(self.x) # 返回x属性的可迭代对象
# 这里的a就是可迭代对象
a = TestIterable('123')
# for循环输出1 2 3
for x in a:
print(x)
next(a) # 这里不能调用next(a)方法,因为没有定义
自定义可迭代器
class TestIterator:
def __init__(self,x):
self.x = x # 获取传入的对象
self.index = 0 # 维护索引值
def __next__(self): # 迭代器必须实现此方法
try:
result = self.x[self.index] # 获取传入对象的值
except IndexError:
raise StopIteration # 如果索引值错误,抛出停止迭代
self.index += 1 # 索引值+1,用来获取传入对象的下一个值
return result # 返回传入对象的值
# 实现此方法才能用于for循环,迭代器可以没有此方法
def __iter__(self):
return iter(self.x)
a = TestIterator([1, 2, 3])
print(next(a))
print(next(a))
for x in a:
print(x)
自定义迭代器,实现自己的迭代逻辑
class Sequence(object):
def __init__(self):
self.num = 2
def __iter__(self):
return self
def __next__(self): # 自己的迭代逻辑,这个迭代器产生小于10的偶数序列
val = self.num
if val>=10:
raise StopIteration
self.num += 2
return val
test_object = Sequence() # test_object即是一个迭代器对象
print(next(test_object))
print(next(test_object))
for i in test_object:
print(i)
为什么要使用迭代器
使用迭代器可以节省空间,举个例子,如果一个很大的列表,如果只需要取前十个数据,直接使用for 循环会把列表全部读到内存中,但是如果使用迭代器则只会一次读一个。
生成器
在 Python 中,使用了 yield 的函数被称为生成器(generator)。
跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。
使用生成器的两种方式
- 第一种:只要把一个列表生成式的[]改成(),就创建了一个generator
- 第二种:如果一个函数中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator。调用函数就是创建了一个生成器(generator)对象。
第一种生成器使用方式
L = [x * x for x in range(10)]
print(type(L)) # L是一个list类型,<class 'list'>
G = (x * x for x in range(10))
print(type(G)) # G是生成器,<class 'generator'>
print(L) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
print(G) # <generator object <genexpr> at 0x130658d60>
print(next(G)) # 既可以使用next()函数也可以使用for循环获取生成器的值
print(next(G))
print(next(G))
for i in G:
print(i)
第二种生成器使用方式
带有 yield 的函数不再是一个普通函数,而是一个生成器generator。
yield相当于 return 返回一个值,并且记住这个返回的位置,下次迭代时,代码从yield的下一条语句开始执行。
def yield_test(n):
for i in range(n):
print('i,',i)
yield i*2
print("i=",i) # 下次迭代时从这条语句开始
print("Done.")
for i in yield_test(3):
print(i)
"""
第一次迭代:i = 0
i,0
0
第二次迭代: i = 1
i=0,
i,1
2
第三次迭代: i = 2
i= 1
i, 2
4
"""