问题描述
我正在编写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等。