python中iterable和iterator(补充enumerate函数)

iterable:可迭代对象

可以一个一个的返回它的成员,比如list,str,tuple,dict,file objects
它可以在for loop种使用,for loop in后面接的必须是一个可迭代对象

iterator:迭代器

是一个表示数据流的对象,可以使用next函数不断的从这个对象里面获取新的数据


前者是一个数据的保存者,一个容器,它可以完全没有状态,可以不知道迭代器数到哪里了,需要有能力产生迭代器,必须要有__iter__或者__getitem___,保证它可以在iter()函数作用下返回一个itetator.而迭代器必须要有__next__方法,保证它被next()作用时返回下一个可迭代对象里面的值的结果

lst = [1,3,5]
for i in lst
	print(i)
##for in 可迭代对象
##做了一个从可迭代对象拿到迭代器的操作等价于
lst = [1,3,5]
it = iter(lst)
for i in it:###还是会对it做一个iter()操作
    print(i)

iter()和next()做了一件什么事情?

_iter_和_next_是两种魔术方法,当我们对一个实例化对象使用内置函数时(这个实例化对象中我们自定义了与这个内置函数对应的魔法方法),相当于我们对这个内置函数进行了重写再使用。
而python中是有内置iter()和next()两个函数的,在对该类实例化对象使用iter()内置函数时,iter()调用我们重写的__iter
()而不是其原本的,返回self。同样的,使用next()内置函数时也即调用我们重写的__next
()而不是原来的
魔法方法是python内置方法,不需要主动调用,存在的目的是为了给python的解释器进行调用,几乎每个魔法方法都有一个对应的内置函数,或者运算符,当我们对这个对象使用这些函数或者运算符时就会调用类中的对应魔法方法,可以理解为重写这些python的内置函数。
我们在调用python类中的某个方法时,通常会看到某些特殊的方法,它们总被双下划线所包围,像这种格式:"__ 方法名__",这些方法很强大,充满魔力,可以让你实现很多功能。如果你的对象实现(重载)了这些方法中的某一个,那么这个方法就会在特殊的情况下被 Python 所调用,你可以定义自己想要的行为,而这一切都是自动发生的。

应用

class NodeIter:
    def __init__(self,node):
        self.curr_node = node

    def __next__(self):
        if self.curr_node is None:
            raise StopIteration
        node,self.curr_node = self.curr_node,self.curr_node.next
        return node

class Node:
    def __init__(self,name):
        self.name = name
        self.next = None
    def __iter__(self):
        return  NodeIter(self)

node1 = Node("node1")
node2 = Node("node2")
node3 = Node("node3")
node1.next = node2
node2.next = node3


for node in node1:
    print(node.name)

image-20221103154836506
第一步首先Node类的iter方法执行NodeIter.init(node1)初始化得到NodeIter(node1),且curr_node=node1
第二步开始执行NodeIter的next方法
image-20221103155018754
根据程序返回node1作为for循环的node变量作为输出,同时讲curr_node变为node2
image-20221103155158048
第三步print之后继续执行NodeIter的next方法:此时该self为
image-20221103155311578
重复上述步骤知道抛出错误
输出结果

node1
node2
node3

以上代码迭代器中没有iter方法,导致如果是下面的情况无法运行(讲可迭代对象执行过一次iter方法之后放在in后面),所以一般加入一个iter在迭代器中直接返回本身即可。

class NodeIter:
    def __init__(self,node):
        self.curr_node = node

    def __next__(self):
        if self.curr_node is None:
            raise StopIteration
        node,self.curr_node = self.curr_node,self.curr_node.next
        return node
    def __iter__(self):
        return self
class Node:
    def __init__(self,name):
        self.name = name
        self.next = None
    def __iter__(self):
        return  NodeIter(self)

node1 = Node("node1")
node2 = Node("node2")
node3 = Node("node3")
node1.next = node2
node2.next = node3
it = iter(node1)
first = next(it)
for node in it:
    print(node.name)

执行完it=it(node1)的变量
image-20221103155843003
下一句
image-20221103155933122
for in先执行NodeIter的iter方法,返回本身,之后再next方法,返回node2作为node变量,再重复直到抛出错误。
输出结果为

node2
node3

enumerate

经测试,它的输入应该是个有实现iter方法的,

class NodeIter:
    def __init__(self,node):
        self.curr_node = node

    def __next__(self):
        if self.curr_node is None:
            raise StopIteration
        node,self.curr_node = self.curr_node,self.curr_node.next
        return node
    def __iter__(self):
        return self
class Node:
    def __init__(self,name):
        self.name = name
        self.next = None
    def __iter__(self):
        return  NodeIter(self)

node1 = Node("node1")
node2 = Node("node2")
node3 = Node("node3")
node1.next = node2
node2.next = node3


# for node in iter(node1):
#     print(node.name)

# it = iter(node1)
# first = next(it)
# for node in it:
#     print(node.name)

for index ,node in enumerate(iter(node1)):
    print(index)
    print(node.name)

它是先执行iter(node1)通过Node的iter获得一个NodeIter实例,再执行in 从NodeIter的iter方法返回本身,再执行next循环,所以如果NodeIter里面没有写iter方法就不可以执行。
输出结果

0
node1
1
node2
2
node3
posted @ 2022-11-03 16:05  kp1793  阅读(150)  评论(0)    收藏  举报