提问人:Elnur 提问时间:11/14/2023 最后编辑:Elnur 更新时间:11/14/2023 访问量:50
链表;TypeError:__str__返回非字符串(类型 NoneType)
Linked list; TypeError: __str__ returned non-string (type NoneType)
问:
我正在研究 Python 3.11 中的链表。我写了书中给出的代码。代码如下:
class Node:
def __init__(self, data, next=None):
self.data = data
self.next = next
class LinkedList:
def __init__(self):
self.head = None
def __str__(self):
node = self.head
while node is not None:
print(node.data)
node = node.next
def append(self, data):
if not self.head:
self.head = Node(data)
return
current = self.head
while current.next:
current = current.next
current.next = Node(data)
def search(self, target):
current = self.head
while current.next:
if current.data == target:
return True
else:
current = current.next
return False
def remove(self, target):
if self.head == target:
self.head = self.head.next
return
current = self.head
previous = None
while current:
if current.data == target:
previous.next = current.next
previous = current
current = current.next
def reverse_list(self):
current = self.head
previous = None
while current:
next = current.next
current.next = previous
previous = current
current = next
self.head = previous
a_list = LinkedList()
a_list.append("Tuesday")
a_list.append("Wednesday")
print(a_list)
import random
a_list = LinkedList()
for i in range(0, 20):
j = random.randint(1, 30)
a_list.search(j)
print(j, end=' ')
当我运行此代码时,出现错误:
回溯(最近一次调用最后一次): 文件 linked_list.py,第 62 行,在 打印(a_list) TypeError:str 返回非字符串(类型 NoneType)
由于函数 str 中的问题,我尝试了以下操作(最后添加 return): 1)
def __str__(self):
node = self.head
while node is not None:
print(node.data)
node = node.next
return node
结果是一样的:
回溯(最近一次调用最后一次): 文件 linked_list.py,第 62 行,在 打印(a_list) TypeError:str 返回非字符串(类型 NoneType)
2)
def __str__(self):
node = self.head
while node is not None:
print(node.data)
node = node.next
return node.data
结果:
回溯(最近一次调用最后一次): 文件“linked_list.py”,第 63 行,在 打印(a_list) 文件“linked_list.py”,第 18 行,在 str 中返回 node.data AttributeError:“NoneType”对象没有属性“data”
答:
代码中存在多个问题:
你问的问题:作者错误地认为它应该打印列表的内容。这不是 的目的。相反,它应该返回列表的字符串版本。调用方可以对此字符串执行某些操作,该字符串可能是打印它或其他内容。
__str__
__str__
快速解决方法是将调用替换为将数据连接成字符串然后返回的代码:
print
def __str__(self): s = "" node = self.head while node is not None: s += f"{node.data} " # don't print, but collect in a string node = node.next return s
不过,这并不是最优雅的方式。您可以从第一个定义中受益,这对其他目的也很有用......
__iter__
search
有一个条件,它检查但没有确保它不是.因此,当列表为空时,此代码将遇到错误。其次,当最后一个节点(仅)具有搜索到的数据时,它不会找到匹配项。条件应为 on ,而不是current.next
current
None
current
current.next
remove
与 和 进行比较。这是不一致的。该函数要么使用节点实例调用,要么使用数据调用。现在你有了一个混合。我想你想用数据来调用,所以第一个陈述是错误的。应首先检查列表是否有节点,然后检查头节点的数据。head
target
current.data
target
remove
if
remove
删除节点后继续循环,尝试查找更多匹配项。这很好,但它与在头节点中处理匹配项的方式不一致,因为当存在匹配项时,您将退出函数。为了保持一致,你不应该退出那里,而是继续前进(既检查头部,然后检查其余节点)。当在循环中找到匹配项时,它会更新为已删除的节点。这是不正确的。例如,这意味着仅删除两个连续匹配节点中的一个。如果匹配项一致,则应保持不变,并引用现在已删除的节点之前的节点。
remove
previous
previous
没问题,但是:
- 驱动程序代码调用但不对返回的值执行任何操作,因此它毫无用处。
a_list.search(j)
- 这个随机的“测试”不会向列表中添加任何节点——它仍然是空的。如果将随机值添加到列表中会更有意义,然后您可以对该方法进行一些正面和负面测试。
search
- 该名称不会显示它返回布尔值(而不是节点或位置)。称其为 or 或 。或者更好的是,定义 ,以便您可以改用运算符。或者更好的是:当你定义了它时,它将被用来解释运算符,所以你实际上可以完全放弃这个方法。
search
has
includes
contains
__contains__
in
__iter__
in
search
- 在名称中添加 是不必要的。这是链表上的一种方法,因此很明显,反转涉及(链接)列表。
_list
reverse_list
以下是该类的建议代码:LinkedList
class LinkedList:
def __init__(self):
self.head = None
def __iter__(self): # Make linked list iterable. Also supports IN operator
node = self.head
while node:
yield node.data
node = node.next
def __str__(self): # Don't print, but return str
# Make use of __iter__
return " ".join(map(str, self))
def append(self, data):
if not self.head:
self.head = Node(data)
return
current = self.head
while current.next:
current = current.next
current.next = Node(data)
def remove(self, target):
# Check in a loop, and don't return:
while self.head and self.head.data == target: # compare data, not node
self.head = self.head.next
current = self.head
previous = None
while current:
if current.data == target:
previous.next = current.next
else: # Only update previous when there is no match
previous = current
current = current.next
def reverse(self): # Better name
current = self.head
previous = None
while current:
next = current.next
current.next = previous
previous = current
current = next
self.head = previous
驱动程序代码可以是:
a_list = LinkedList()
a_list.append("Tuesday")
a_list.append("Wednesday")
a_list.append("Wednesday")
a_list.append("Thursday")
print(a_list)
a_list.remove("Wednesday")
print("Does it have Tuesday? ", "Tuesday" in a_list)
print(*a_list)
上一个:链表节点创建和非法内存访问
下一个:在 C 中使用链表实现队列
评论
while node is not None:
node
.data
print
__str__
__str__