定制类迭代器,就是让我自己定义的类,可以用for循环语句来迭代遍历,以下是我自定义的一个类Users:
class Users(object): def __init__(self,user): self.users=[user] def __str__(self): # __str__() return str(self.users) def __add__(self,user): # 重载操作符‘+’ self.users.append(user) return self #定制类迭代器希望实现的功能,用for语句遍历Users对象实例中的用户user: for user in Users: print (user)要想实现以上功能,就需要了解for循环机制和迭代器协议的相关概念。
1. 迭代器协议相关概念(参考:https://blog.csdn.net/weixin_41212405/article/details/80586002)
- 迭代器协议:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个Stoplteration异常。以终止次迭代(只能往后走不能往前退)。
- 可迭代对象:实现了迭代器协议的对象(如何实现:对象内部定义一个__iter__()方法)
以上是概念,还需要与for循环机制结合一起理解
2. for循环机制:
以下是对for循环的一个模拟(可能不成熟):
首先,for语句需要接收一个可迭代对象(对应我们的Users),为将Users实现为可迭代对象,就需要在Users类定义中实现__iter__()方法
然后,调用__iter__()返回的可迭代对象中__next__()方法实现对可迭代对象的遍历
有两点注意事项:
- Users可能并不是实际的可迭代对象,要根据__iter__()的返回值判断(见后续代码分析)
- __init__()的功能只是为了返回可迭代对象,而实现在可迭代对象上实现迭代遍历的主要功能则是有__next__()实现的
def for_statement(iterator_obj): while True: try: print(iterator_obj.__iter__().__next__()) except StopIteration: pass for user in Users: print (user)根据以上内容,我把Users类代码实现如下:
以下代码,我有两个疑问:
1. __iter__() 该方法的返回值如何确定?
这边返回的可迭代对象,并非Users类对象本身(return self),而是Users对象的数据属性列表(return iter(self.users))
2. 为什么没有实现__next__(),for语句仍可正常工作?
参考第1点,for语句工作时,找到的可迭代对象是Users实例的数据属性,即一个列表(self.users),而列表本身已经定义类__next__()方法; for语句不会去调用Users类里面定义的__next__()方法
#2.重载操作符 & 序列迭代器 class Users(object): def __init__(self,user): self.users=[user] def __str__(self): # __str__() return str(self.users) def __add__(self,user): # 重载操作符‘+’ self.users.append(user) return self def __iter__(self): return iter(self.users) # 该方法的返回值如何确定? #def __next__(self): #为什么没有实现__next__(),for语句仍可正常工作? #pass #测试部分------------------------------------------------------ users=Users("zhangsan") users+"lisi" users+"wangwu" print(users) for u in users: print("hahah:",u) #输出结果:---------------------------------------------------- ['zhangsan', 'lisi', 'wangwu'] hahah: zhangsan hahah: lisi hahah: wangwu1. 本文的代码直接调用类列表的__next__(),这种实现方法是否正确,看廖雪峰的官方网站以及《python核心编程》的例子可迭代对象都是直接返回类对象本身。
2.列表__next__()方法又是如何实现,本文是否可以借鉴。
3.如何定制一个链表的类迭代器呢,__next__()实现方法是不是又和本文不一样呢?
待续。。。。。。。。。。。。。。。。。。。。
