属性错误Nonetype没有属性getItem

问题描述

我正在编写LinkedList数据类型的实现,但是当我包含__contains____iterate____delitem____str____repr__功能

class LinkedList:

    # The __Node class is used internally by the LinkedList class. It is
    # invisible from outside this class due to the two underscores
    # that precede the class name. Python mangles names so that they
    # are not recognizable outside the class when two underscores
    # precede a name but aren't followed by two underscores at the
    # end of the name (i.e. an operator name).
    class __Node:
        def __init__(self,item,next=None):
            self.item = item
            self.next = next

        def getItem(self):
            return self.item

        def getNext(self):
            return self.next

        def setItem(self,item):
            self.item = item

        def setNext(self,next):
            self.next = next

    def __init__(self,contents=[]):
        # Here we keep a reference to the first node in the linked list
        # and the last item in the linked list. The both point to a
        # dummy node to begin with. This dummy node will always be in
        # the first position in the list and will never contain an item.
        # Its purpose is to eliminate special cases in the code below.
        self.first = LinkedList.__Node(None,None)
        self.last = self.first
        self.numItems = 0

        for e in contents:
            self.append(e)

    def __getitem__(self,index):
        if index >= 0 and index < self.numItems:
            cursor = self.first.getNext()
            for i in range(index):
                cursor = cursor.getNext()

            return cursor.getItem()

        raise IndexError("LinkedList index out of range")

    def __setitem__(self,index,val):
        if index >= 0 and index < self.numItems:
            cursor = self.first.getNext()
            for i in range(index):
                cursor = cursor.getNext()

            cursor.setItem(val)
            return

        raise IndexError("LinkedList assignment index out of range")

    def insert(self,item):
        cursor = self.first

        if index < self.numItems:
            for i in range(index):
                cursor = cursor.getNext()

            node = LinkedList.__Node(item,cursor.getNext())
            cursor.setNext(node)
            self.numItems += 1
        else:
            self.append(item)

    def __add__(self,other):
        if type(self) != type(other):
            raise TypeError("Concatenate undefined for " + \
                str(type(self)) + " + " + str(type(other)))

        result = LinkedList()

        cursor = self.first.getNext()

        while cursor != None:
            result.append(cursor.getItem())
            cursor = cursor.getNext()

        cursor = other.first.getNext()

        while cursor != None:
            result.append(cursor.getItem())
            cursor = cursor.getNext()

        return result

    def __contains__(self,item):
        cursor = self.first.getNext()
        while cursor != None:
            cursor = cursor.getNext()
            curItem = cursor.getItem()
            if curItem == item:
                return True
        return False

    def __delitem__(self,index):
        cursor = self.first.getNext()
        if index < self.numItems:
            for i in range(index - 1):
                cursor = cursor.getNext()
            delIndex = cursor.getNext()
            nextref = delIndex.getNext()
            cursor.getNext(nextref)
            self.numItems -= 1

    def __eq__(self,other):
        if type(other) != type(self):
            return False

        if self.numItems != other.numItems:
            return False

        cursor1 = self.first.getNext()
        cursor2 = other.first.getNext()
        while cursor1 != None:
            if cursor1.getItem() != cursor2.getItem():
                return False
            cursor1 = cursor1.getNext()
            cursor2 = cursor2.getNext()

        return True

    def __iter__(self):
        cursor = self.first.getNext()
        while cursor != None:
            cursor = cursor.getNext()
            curItem = cursor.getItem()
            yield curItem

    def __len__(self):
        return self.numItems

    def append(self,item):
        node = LinkedList.__Node(item)
        self.last.setNext(node)
        self.last = node
        self.numItems += 1

    def __str__(self):
        cursor = self.first.getNext()
        s="["
        while cursor != None:
            cursor = cursor.getNext()
            s = s + str(cursor.getItem())
            s = s + ","
        s = s + "]"
        return s

    def __repr__(self):
        cursor = self.first.getNext()
        s = "PyList(["
        while cursor != None:
            cursor = cursor.getNext()
            curItem = cursor.getItem()
            s = s + str(curItem)
            s = s +","
        s = s + "])"


def main():
    lst = LinkedList()

    for i in range(100):
        lst.append(i)

    lst2 = LinkedList(lst)

    print(lst)
    print(lst2)

    if lst == lst2:
        print("Test 1 Passed")
    else:
        print("Test 1 Failed")

    lst3 = lst + lst2

    if len(lst3) == len(lst) + len(lst2):
        print("Test 2 Passed")
    else:
        print("Test 2 Failed")

    if 1 in lst3:
        print("Test 3 Passed")
    else:
        print("Test 3 Failed")

    if 2 in lst3:
        print("Test 4 Passed")
    else:
        print("Test 4 Failed")

    del lst[1]

    if 1 in lst:
        print("Test 5 Failed")
    else:
        print("Test 5 Passed")

    if len(lst) == 99:
        print("Test 6 Passed")
    else:
        print("Test 6 Failed")

    if lst == lst2:
        print("Test 7 Failed")
    else:
        print("Test 7 Passed")

    del lst2[2]

    if lst == lst2:
        print("Test 8 Failed")
    else:
        print("Test 8 Passed")


    lst4 = LinkedList(lst)
    lst.insert(0,100)
    lst4 = LinkedList([100]) + lst4

    if lst == lst4:
        print("Test 9 Passed")
    else:
        print("Test 9 Failed")

    lst.insert(1000,333)
    lst4.append(333)

    if lst == lst4:
        print("Test 10 Passed")
    else:
        print("Test 10 Failed")

    print(lst)
    print(lst4)


if __name__ == "__main__":
    main()

我得到的错误是:

Traceback (most recent call last):
  File "main.py",line 247,in <module>
    main()
  File "main.py",line 173,in main
    lst2 = LinkedList(lst)
  File "main.py",line 36,in __init__
    for e in contents:
  File "main.py",line 134,in __iter__
    curItem = cursor.getItem()
AttributeError: 'nonetype' object has no attribute 'getItem'

解决方法

问题在于您如何迭代光标。

  • 您要为光标分配第一项。
  • 立即将其移至下一个元素,而没有机会使用第一项。
  • 因此,当光标到达末尾时,它已经为None,无法处理。

更改为:

  • 将链接列表中的第一项分配给光标。
  • 当光标不是None时,处理光标中的元素。
  • yield值之前,仅将光标移动一步。

迭代功能

    def __iter__(self):
        cursor = self.first.getNext()
        while cursor != None:
            curItem = cursor.getItem()
            cursor = cursor.getNext()
            yield curItem

类似地也更改其他功能-str,contains等。