for
循环的对象,统称为可迭代对象:Iterable
isinstance(obj, Iterable)
进行判断, 若返回为True
则是,反之则不是;__iter__
方法则称为可迭代对象;from collections import Iterable, Iterator
class Classmate(object):
def __init__(self):
self.name = list()
def add(self, name):
self.name.append(name)
if __name__ == '__main__':
c = Classmate()
c.add("张三")
c.add("李四")
c.add("王五")
print("c 是否是可迭代对象:", isinstance(c, Iterable))
# 实例 c 中不含有 __iter__ 方法时,判断显示为 False,即不可迭代对象
c 是否是可迭代对象: False
__iter__
方法时from collections import Iterable, Iterator
class Classmate(object):
def __init__(self):
self.name = list()
def add(self, name):
self.name.append(name)
def __iter__(self):
pass
if __name__ == '__main__':
c = Classmate()
c.add("张三")
c.add("李四")
c.add("王五")
print("c 是否是可迭代对象:", isinstance(c, Iterable)) # 当注释掉类中的 __iter__ ,这里判断会变为 False
# 实例 c 中不含有 __iter__ 方法时,判断显示为不可迭代对象
c 是否是可迭代对象: True
next()
函数调用并不断返回下一个值的对象称为迭代器;iter()
函数作用于可迭代对象之后生成的对象称为迭代器;isinstance(obj, Iterator)
进行判断, 若返回为True
则是,反之则不是;iter()
函数作用于可迭代对象之后生成的对象,并且该对象含有 __iter__
和 __next__
方法;from collections import Iterable, Iterator
class Classmate(object):
def __init__(self):
self.name = list()
def add(self, name):
self.name.append(name)
def __iter__(self):
# pass
return ClassIterator()
class ClassIterator(object):
def __iter__(self):
pass
def __next__(self):
pass
if __name__ == '__main__':
c = Classmate()
c.add("张三")
c.add("李四")
c.add("王五")
print("c 是否是可迭代对象:", isinstance(c, Iterable)) # 当注释掉类中的 __iter__ ,这里判断会变为 False
print("c 是否是迭代器:", isinstance(c, Iterator))
d = iter(c)
print("d 是否是迭代器:", isinstance(d, Iterator))
c 是否是可迭代对象: True
c 是否是迭代器: False
d 是否是迭代器: True # 当注释掉 类 ClassIterator 中的任意一个方法,该返回值为 False 或报错
先弄清楚,不论是 for 循环是从可迭代对象还是迭代器中取值,都是调用的该对象的 __next__
方法返回的值,那问题来了,可迭代对象中比如上述代码中的类 Classmate
没有 __next__
方法就不能取值了?这里答案是否定的,因为类 Classmate
中还有 __iter__
方法, 调用该方法若返回的对象中有 __next__
方法,仍旧可以取该方法的返回值;
class Classmate(object):
def __init__(self):
self.name = list()
def add(self, name):
self.name.append(name)
def __iter__(self):
# pass
return ClassIterator()
class ClassIterator(object):
def __iter__(self):
pass
def __next__(self):
return 111
if __name__ == '__main__':
c = Classmate()
c.add("张三")
c.add("李四")
c.add("王五")
for i in c:
print(i)
控制台会不断打印类 ClassIterator
中的 __next__
方法的输出 111,这个结果肯定不是我们希望的,我们希望打印我们添加的名称;
略
于是我们继续改造代码如下:
class Classmate(object):
def __init__(self):
self.name = list()
def add(self, name):
self.name.append(name)
def __iter__(self):
# pass
return ClassIterator(self)
class ClassIterator(object):
def __init__(self, obj):
self.obj = obj
self.num = 0
def __iter__(self):
pass
def __next__(self):
res = self.obj.name[self.num]
self.num += 1
return res
if __name__ == '__main__':
c = Classmate()
c.add("张三")
c.add("李四")
c.add("王五")
for i in c:
print(i)
Traceback (most recent call last):
张三
File "/Users/wawa/Desktop/code/03协程/迭代器.py", line 46, in
李四
for i in c:
王五
File "/Users/wawa/Desktop/code/03协程/迭代器.py", line 32, in __next__
res = self.obj.name[self.num]
IndexError: list index out of range
继续优化:
class Classmate(object):
def __init__(self):
self.name = list()
def add(self, name):
self.name.append(name)
def __iter__(self):
# pass
return ClassIterator(self)
class ClassIterator(object):
def __init__(self, obj):
self.obj = obj
self.num = 0
def __iter__(self):
pass
def __next__(self):
if self.num < len(self.obj.name):
res = self.obj.name[self.num]
self.num += 1
return res
else:
raise StopIteration
if __name__ == '__main__':
c = Classmate()
c.add("张三")
c.add("李四")
c.add("王五")
for i in c:
print(i)
张三
李四
王五
真的是一个好问题~其实这里也是手写迭代器实现 for 循环的逻辑,继续优化代码如下:
class Classmate(object):
def __init__(self):
self.name = list()
self.num = 0
def add(self, name):
self.name.append(name)
def __iter__(self):
# pass
# return ClassIterator(self)
return self
def __next__(self):
if self.num < len(self.name):
res = self.name[self.num]
self.num += 1
return res
else:
raise StopIteration
if __name__ == '__main__':
c = Classmate()
c.add("张三")
c.add("李四")
c.add("王五")
for i in c:
print(i)
张三
李四
王五