如何在Python中无None错误地正向打印链表?
问题背景
我实现了一个简单链表,目前能实现反向打印(先添加的节点最后输出),但想要实现正向打印时,总是遇到和None相关的错误。
错误代码与报错信息
我最初的实现代码:
class Node: def __init__(self, data): self.data = data self.next = None def addNextData(self, data): self.next = Node(data) return self.next def __str__(self): if(self is None): return "None" print(self.data) return print(self.next) node = Node("a") node.addNextData("b") \ .addNextData("c") \ .addNextData("d") print(node)
运行后抛出错误:
Traceback (most recent call last): TypeError: __str__ returned non-string (type NoneType)
尝试的其他写法
我改成下面的写法后,虽然不报错,但会打印多余的空字符串/空行:
def __str__(self): if(self is None): return "None" print(self.data) print(self.next) return ""
我已经能用迭代方式实现正向打印,但想找更优雅的递归/打印实现:
def __str__(self): head = self str = '' while(head is not None): str = str + head.data + '->' head = head.next return str + 'None'
两个关键疑惑
- 为什么下面这种反向打印的写法不会抛出
None相关错误?
def __str__(self): print(self.next) return self.data
- 直接执行
print(None)为什么不会报错?
问题解析与解决方案
1. 初始代码报错的原因
Python规定__str__方法必须返回字符串,但你写的return print(self.next)里,print()函数本身的返回值是None,直接返回它就违反了__str__的类型要求,所以触发TypeError。
另外,if(self is None)这个判断完全没用——__str__是Node实例的方法,只有当实例存在时才会被调用,self不可能是None。当遍历到链表最后一个节点时,self.next是None,此时print(self.next)是合法的,但返回print的结果(None)才是错误根源。
2. 空行问题的由来
改成返回空字符串的写法后,虽然满足了__str__返回字符串的要求,但print(self.next)会在打印当前节点数据后,额外打印最后一个节点的next(也就是None),再加上print(node)会输出__str__返回的空字符串,所以会多出来一个空行。
3. 优雅的递归正向打印实现
递归的正确姿势是拼接字符串而非直接打印,这样既符合__str__的要求,又能实现正向输出:
def __str__(self): if self.next is None: return f"{self.data}->None" return f"{self.data}->{self.next}"
调用print(node)会直接输出a->b->c->d->None,没有多余内容,完全满足需求。
4. 反向打印写法不报错的原因
反向打印的代码里,print(self.next)会先递归触发后续节点的__str__,而每个__str__最终都返回了当前节点的data(字符串类型),完全符合__str__的返回要求,所以不会报错。具体执行流程是:
- 调用
print(node)时,先执行node.__str__里的print(node.next) - 这会触发b节点的
__str__,进而执行print(b.next),以此类推直到d节点 - d节点的
print(d.next)就是print(None),这一步合法;然后d节点返回"d",b节点的print输出"d",接着b节点返回"b" - 最后node的
print输出"a",整体打印顺序是None、d、c、b、a,也就是反向打印,全程没有返回非字符串的情况。
5. print(None)为什么合法?
print()是Python内置函数,它可以接受任意类型的参数,当传入None时,会自动将其转换为字符串"None"并打印,这是内置函数的默认处理逻辑,所以不会报错。
内容的提问来源于stack exchange,提问作者Rick J

