修改前代码:
请详见《使用python实现链表》
进行单元测试代码:
import unittest
from unittest.mock import patch
from test import LinkedList, Node
link = LinkedList()
data = ['张三', '李四', '王二']
link.init_link(data)
class TestLinkedList(unittest.TestCase):
def test01_init(self):
num = link.num
self.assertEqual(len(data), num) # 断言两个参数的值相等
head_node = link.head
self.assertTrue(head_node.data == '张三') # 断言头节点的数据域的值为张三
def test02_append(self):
with patch('builtins.print') as mocked_print:
link.append('秦国宇')
mocked_print.assert_called_with('操作成功!') # 比对函数最后返回的打印数据
link.append('12123')
mocked_print.assert_called_with('操作成功!')
def test03_remove(self):
with patch('builtins.print') as mocked_print:
link.remove('秦国宇')
mocked_print.assert_called_with('操作成功!')
link.remove('埃达尼斯')
mocked_print.assert_called_with('链表中不存在的对象!')
link.remove('10')
mocked_print.assert_called_with('链表中不存在的对象!')
link.remove('0')
mocked_print.assert_called_with('操作成功!')
def test04_insert(self):
with patch('builtins.print') as mocked_print:
link.insert('赵六', 1)
mocked_print.assert_called_with('操作成功!')
link.insert('正式开课了', 100)
mocked_print.assert_called_with('链表中不存在的对象!')
def test05_change(self):
with patch('builtins.print') as mocked_print:
link.change('张三', 0)
mocked_print.assert_called_with('操作成功!')
link.change('啥的', 100)
mocked_print.assert_called_with('链表中不存在的对象!')
def test06_getitem(self):
self.assertTrue(isinstance(link.getitem(1).data, str))
self.assertEqual(link.getitem(1), link.getitem(0).next_node)
def test07_size(self):
self.assertTrue(isinstance(link.size(), int))
self.assertEqual(link.size(), link.num)
def test08_clear(self):
link.clear()
self.assertEqual(link.size(), 1)
self.assertEqual(link.head, None)
if __name__ == '__main__':
unittest.main()
经过单元测试,修改后的代码:
# crontab
class Node(object):
def __init__(self, data):
self.data = data # 节点的数据
self.next_node = None
# def set_next_node(self, node):
# self.next_node = node
def __repr__(self):
return self.data # 格式化输出
class LinkedList(object):
def __init__(self):
self.head = None # 链表的头节点
self.num = None # 链表的长度
def append(self, data):
"""在尾部添加一个节点"""
p = self.getitem(self.num - 1) # 获取尾部节点
p.next_node = Node(data) # 给尾部节点的下一节点赋值
self.num += 1 # 总长增加1
print('操作成功!')
def remove(self, index):
"""移除链表中的某一个节点"""
if index.isdigit() and int(index) in range(self.num): # 如果index全是数字并且在0,到总长度减一的范围中
p = self.getitem(int(index)) # 获取当前节点
if p is not self.head: # 如果当前节点不是头节点
p_pre = self.getitem(int(index) - 1) # 获取上一个节点
p_pre.next_node = p.next_node # 上一节点的下一节点变为要删除节点的下一节点
else:
self.head = p.next_node # 当前节点是头节点则, 头节点变为下一个节点
self.num -= 1 # 长度减一
print('操作成功!')
elif not index.isdigit():
node = self.head
pre_node = None # 记录前一个节点
for i in range(self.num):
if index == node.data: # 如果index和某个数据的节点数据一样
if pre_node == None: # 如果没有前一个节点,就为头节点
self.head = node.next_node # 头节点等于原头节点的下一节点
else:
pre_node.next_node = node.next_node # 前一节点的下一个节点等于想要删除的当前节点的下一节点
self.num -= 1
print('操作成功!')
break # 找到了第一个节点就直接退出循环
node, pre_node = node.next_node, node
if i + 1 == self.num:
print('链表中不存在的对象!')
else:
print('链表中不存在的对象!')
def insert(self, data, index):
"""在链表中的某个位置插入一个节点"""
if index < self.num - 1:
current_p = self.getitem(index) # 获取想要插入位置节点
node = Node(data) # 创建新节点
if index == 0: # 在头节点前插入一条数据
node.next_node, self.head = self.head, node
elif index == self.num - 1: # 表示想要在最后一个位置插入一个节点
current_p.next_node = node
elif index < self.num - 1:
next_node = self.getitem(index + 1) # 获取想要插入位置的下一节点
current_p.next_node = node
node.next_node = next_node # 获取下一个节点
self.num += 1
print('操作成功!')
else:
print('链表中不存在的对象!')
def change(self, data, index):
"""改变某一节点的数据"""
if index <= self.num - 1:
current_p = self.getitem(index) # 获取当前节点
current_p.data = data # 修改
print('操作成功!')
else:
print('链表中不存在的对象!')
def init_link(self, data):
"""创建一个新的链表"""
self.head = Node(data[0])
p = self.head
for i in data[1:]:
node = Node(i)
p.next_node = node
p = node
self.num = self.size()
def getitem(self, index):
"""获取某一个位置的节点"""
p = self.head
for i in range(index):
p = p.next_node
return p
def size(self):
"""获取当前链表的长度"""
p = self.head
index = 1
if p: # 首先判断head是否为None
while p.next_node: # 如果当前节点还有下一个节点的地址, 则表示后面还存在节点, 如果为空,则没有了
index += 1
p = p.next_node
return index
def all_node(self):
"""获取链表中的所有数据"""
for i in range(self.num):
print('%s: %s' % (i + 1, self.getitem(i)))
def clear(self):
"""清空链表"""
self.head = None
print('操作成功!')
def menu():
print()
print('-------------------------------------------------------')
print('*****************欢迎使用学生查询系统********************')
print('******************1. 查看学生总人数*********************')
print('******************2. 查看所有学生 *********************')
print('******************3. 尾部添加学生 *********************')
print('******************4. 插入一个学生 *********************')
print('******************5. 删除一个学生 *********************')
print('******************6. 查看某个学生 *********************')
print('******************7. 修改学生名字 *********************')
print('******************8. 退出本系统 *********************')
print('-------------------------------------------------------')
print()
def switch_choose(link, num):
if num == 1:
print('学生共有%s个' % link.size())
if num == 2:
link.all_node()
if num == 3:
name = input('请输入学生名字:')
link.append(name)
if num == 4:
name = input('请输入学生名字:')
index = int(input('请输入要插入的位置:'))
link.insert(name, index)
if num == 5:
index_or_name = input('请输入想要移除的学生的位置或者名字:')
link.remove(index_or_name)
if num == 6:
index = int(input('请输入想要查看学生的位置:'))
print(link.getitem(index))
if num == 7:
name = input('请输入学生名字:')
index = int(input('请输入要改变的学生的位置:'))
link.change(name, index)
def main(data):
link = LinkedList() # 构造一个对象
link.init_link(data) # 创建一个新的链表
while True:
menu()
choose = int(input('请选择操作选项:'))
if choose == 8:
break
switch_choose(link, choose)
if __name__ == '__main__':
student_list = ['张三', '李四', '王五']
main(student_list)