
Python列表,元组,集合和字典均支持使用for循环. Python for循环还使遍历可迭代对象的每个元素变得容易,因此如何自定义一个类以使其实现Python循环呢?
为了更好地说明此方法,我以单链列表为例:
class Node(object):
def __init__(self, item, next_=None):
self.item = item
self.next = next_
class SLList(object):
def __init__(self, item):
self.__sentinel = Node(0)
self.__sentinel.next = Node(item)
self.__size = 1
# 属性绑定,使得self.size无法被用户赋值
@property
def size(self):
return self.__size
def addFirst(self, item):
self.__sentinel.next = Node(item, self.__sentinel.next)
self.__size += 1
def addLast(self, item):
p = self.__sentinel
while P.next is not None:
p = p.next
p.next = Node(item)
self.__size += 1

其中,Node类是一个单链列表节点类,SLList是一个带有哨兵的单链列表,我只是在这里简单地实现了一些addFirst和addLast方法.
首先,让我们回顾一下Java如何实现增强的for循环(即每个循环). 相似的代码如下:
/* Singly linked list with generics*/
public class SLList<T> implements Iterable<T> {
private Node sentinel;
private int size;
private class Node{
T item;
Node next;
public Node(T item, Node next){
this.item = item;
this.next = next;
}
}
public SLList(T item){
size = 1;
sentinel.next = new Node(item, null);
}
public void addFirst(T item){
sentinel.next = new Node(item, sentinel.next);
size++;
}
public void addLast(T item){
Node p = this.sentinel;
while (p.next != null){
p = p.next;
}
p.next = new Node(item, null);
}
private class SLListIterator implements Iterator<T>{
private Node pointer = sentinel;
@Override
public boolean hasNext() {
return pointer.next != null;
}
@Override
public T next() {
pointer = pointer.next;
return pointer.item;
}
}
@Override
public Iterator<T> iterator() {
return new SLListIterator();
}
}
在Java中,我们使SLList类实现可迭代的接口以返回Iterator对象. 在for each循环中,我们实际上调用SLList.iterator()方法来获取Iterator对象,然后调用Iterator对象的next方法,直到hasNext方法返回false为止.
接下来,我们回到python. Python实现for循环的主要方法有两种for循环 链表,分别是__iter__和__next__方法,它们分别对应于两个内置函数iter和next. 以下是一个缓慢的操作:
在for i in range(3)语句中,可迭代对象首先由内置函数iter生成,然后连续调用该对象的next方法并将其分配给变量i,直到该对象报告“ StopIteration”,此错误发生时将停止迭代.

for i in range(3):
print(i) # 依次打印
it = iter([0,1,2])
print(next(it))
print(next(it))
print(next(it))
print(next(it)) # Traceback: StopIteration
好的,那么我们如何才能使自定义单链列表支持普通列表和元组之类的循环呢?
首先,我们编写__iter__方法,该方法返回一个可迭代的对象. 该对象支持下一个方法,并且在没有下一个方法时会引发StopIteration错误(就像Java的.iterator()方法返回一样,使用.next()和.hasNext()方法实现Iterable接口的对象是相同的) . 那么我们如何定义__iter__方法返回的对象?在这里,我给出两个想法:

第一个想法: 返回链表本身(自身)并将其写入链表的__next__方法. 示例代码如下:
def __iter__(self):
self.__pointer = self.__sentinel
return self
def __next__(self):
while self.__pointer.next is not None:
self.__pointer = self.__pointer.next
return self.__pointer.item
else:
raise StopIteration()
在每次迭代的开始(__iter__方法的第一行)for循环 链表,我们使指针指向前哨并返回self. 当指针不为空时,我们将其用作__next__方法的返回值;当指针为空时,我们将引发StopIteration()
第二个想法: 定义一个遍历链表所有节点的,我们可以使用此附带的next()方法,示例代码:
def __travel(self):
p = self.__sentinel.next
while p is not None:
yield p.item
p = p.next
def __iter__(self):
return self.__travel
在这里,我们将迭代器函数返回到iter方法. 迭代器本身支持__next__方法. 所以,它有效!!!
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-183245-1.html
放家里跟放银行里都贬吧