b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

如何在自定义类中优雅地实现Python的for循环-以链接列表为例

电脑杂谈  发布时间:2020-04-21 06:04:02  来源:网络整理

foreach循环与for循环_for循环 链表_for循环 链表

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

foreach循环与for循环_for循环 链表_for循环 链表

其中,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();
    }
}

for循环 链表_foreach循环与for循环_for循环 链表

在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”,此错误发生时将停止迭代.

foreach循环与for循环_for循环 链表_for循环 链表

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__方法返回的对象?在这里,我给出两个想法:

foreach循环与for循环_for循环 链表_for循环 链表

第一个想法: 返回链表本身(自身)并将其写入链表​​的__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

    相关阅读
      发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

      • 吴千能
        吴千能

        放家里跟放银行里都贬吧

      热点图片
      拼命载入中...