一、什么是定制类迭代器
定制类迭代器,就是让我自己定义的类,可以用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循环机制和迭代器协议
要想实现以上功能,就需要了解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类的代码实现
根据以上内容,我把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: wangwu
四、Others
1. 本文的代码直接调用类列表的__next__(),这种实现方法是否正确,看廖雪峰的官方网站以及《python核心编程》的例子可迭代对象都是直接返回类对象本身。
2.列表__next__()方法又是如何实现,本文是否可以借鉴。
3.如何定制一个链表的类迭代器呢,__next__()实现方法是不是又和本文不一样呢?
待续。。。。。。。。。。。。。。。。。。。。