大数跨境

Python中的可迭代对象和迭代器

Python中的可迭代对象和迭代器 慧测
2021-03-15
2
导读:一文搞懂Python中的可迭代对象和迭代器

什么叫可迭代对象?


不专业:可以直接作用于 for 循环的对象,统称为可迭代对象:Iterable

稍微专业:通过 Python 内置方法 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

# 当给类 Classmate 加上 __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("王五")  # 当注释掉类中的 __iter__ ,这里判断会变为 False print("c 是否是可迭代对象:", isinstance(c, Iterable))

# 测试结果如下:

# 实例 c 中不含有 __iter__ 方法时,判断显示为不可迭代对象c 是否是可迭代对象:True

什么叫迭代器?


不专业1:可以被next()函数调用并不断返回下一个值的对象称为迭代器;

不专业2:通过 iter() 函数作用于可迭代对象之后生成的对象称为迭代器;

稍微专业:通过 Python 内置方法 isinstance(obj, Iterator) 进行判断, 若返回为True则是,反之则不是;

专业解释:通过 iter() 函数作用于可迭代对象之后生成的对象,并且该对象含有 __iter__ __next__ 方法;

from collections import Iterable, Iteratorclass 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("王五") # 当注释掉类中的 __iter__ ,这里判断会变为 False print("c 是否是可迭代对象:", isinstance(c, Iterable)) print("c 是否是迭代器:", isinstance(c, Iterator)) d = iter(c)  print("d 是否是迭代器:", isinstance(d, Iterator))

# 测试结果如下:

c 是否是可迭代对象:Truec 是否是迭代器:False # 当注释掉 类 ClassIterator 中的任意一个方法,该返回值为 False 或报错d 是否是迭代器:True      

那么问题来了,什么时候可以用 for 循环去从可迭代对象或者迭代器中进行取值呢?

先弄清楚,不论是 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 <module>李四    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)

# 测试结果如下:

张三李四王五


慧测三大经典课程体系之性能测试——

课程特点:时间长,费用低,干货多

————————————————

版权声明:本文为CSDN博主「SZ_ChenBolin」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/weixin_39386145/article/details/113619581

【声明】内容源于网络
0
0
慧测
专注人工智能前沿技术落地企业实战应用
内容 404
粉丝 0
慧测 专注人工智能前沿技术落地企业实战应用
总阅读104
粉丝0
内容404