我们都知道想列表也是一个对象,相对列表进行循环遍历,这里隐藏一个条件,就是列表本身是一个数据存储的区间,哪怕只有一个元素。如果想对一个数据类型进行迭代,那么他必须是一个可迭代对象。想对对象进行遍历和迭代也是这样,这个对象的性质就必须得满足遍历和迭代这两个条件。
一、遍历对象
如何让对象满足遍历条件?这里需要给对象一个满足遍历的区间,在python中使用__getitem__()这个函数来实现就可以了。
class Cat:
def __init__(self, num):
self.num = num
def __getitem__(self, item):
self.num += 1
if self.num >= 8: # 加个终止条件
raise StopIteration('遍历结束')
return self.num
c = Cat(3)
print(type(c))
for i in c:
print(i)
返回结果:
<class '__main__.Cat'>
4
5
6
7
从上面的代码可以看出来,先给对象传递一个3作为起始数据,然后通过getitem方法中的判断给他一个终止条件,只要满足判断条件就直接返回num本身,这段代码完全可以理解为对num本身的操作。
二、迭代对象
1.方法1:直接通过iter函数把类中的列表转为可迭代对象
class Cat:
def __init__(self, num):
self.num = num
def __iter__(self):
return iter(self.num) # 返回一个可迭代对象给下面的实例
list1 = [1, 2, 3, 4, 5, 6]
c = Cat(list1)
for i in c:
print(i)
虽然这种操作方法可以实现,但是显得有些多余,因为我们直接对列表进行迭代就处理就可以了,不需要通过类来封装。
2.方法2:在类的内部使用next方法来实现可迭代
class Cat:
def __init__(self, num): # 这里num是整数
self.num = num
def __iter__(self): # 此方法一般用转换一个可迭代对象成为迭代器
# return iter(self.num)
return self # 这里的self实例是不可迭代的,所以要增加一个__next__方法来完善
def __next__(self):
self.num += 1 # 和上面的for循环不一样,这里的+=1是指指针每次偏移1,上面的for循环是下标变化
if self.num >= 10: # 加个终止条件
raise StopIteration('遍历结束')
return self.num
# list1 = [1, 2, 3, 4, 5, 6]
# b = Cat(list1)
c = Cat(1)
for i in c:
print(i)
上面代码中把列表注释了,首先通过iter函数把self也就是对象本身转化成一个迭代器,但是这时候还是无法迭代遍历,然后通过next内置函数给列表一个终止条件,也就是指针移动条件,显现迭代遍历。
3.方法3:上面的实例通过__next__()方法的加持,可以直接使用next在外界对对象进行迭代访问。
class Cat:
def __init__(self, num): # 这里num是整数
self.num = num
def __iter__(self):
# return iter(self.num)
return self # 这里的self实例是不可迭代的,所以要增加一个__next__方法来完善
def __next__(self):
self.num += 1 # 和上面的for循环不一样,这里的+=1是指指针每次偏移1,上面的for循环是下标变化
if self.num >= 4: # 加个终止条件
raise StopIteration('遍历结束')
return self.num
c = Cat(1) # 从1到4
print(next(c))
print(next(c))
# print(next(b)) # StopIteration: 遍历结束
总结:判断对象是不是迭代器:必须要实现__iter__()和__next__()两个方法。
import collections.abc
print(isinstance(c, collections.abc.Iterator)) # 是不是迭代器:需要实现__iter__()和__next__()两个方法
print(isinstance(c, collections.abc.Iterable)) # 是不是可迭代的对象:只要实现__iter__这一个方法