如何在 Python 3.6 中将 __str__() 和 __repr__() 用于单向链表?

How do I use __str__() and __repr__() for a singly linked list in Python 3.6?

大家。我遇到了一些需要解决的问题,我希望得到一些关于该怎么做的帮助。所以,我有这个 Python 3.6 我一直在做的作业,关于单链表。到目前为止,我的大多数 appending/prepending 测试用例、从前面和后面删除以及完全删除节点都进行得很顺利。但是,我的一些测试用例存在一些问题。问题围绕着我对 __str__(self)__repr__(self) 函数的使用。

下面是我提供的代码。 (编辑:我只留下了有问题需要修复的测试代码。所有其他测试用例都很好):

class LinkedList(object):
    class Node(object):
        # pylint: disable=too-few-public-methods
        ''' no need for get or set, we only access the values inside the
        LinkedList class. and really: never have setters. '''

        def __init__(self, value, next = None):
            self.value = value
            self.next = next

        def __repr__(self):
            return repr(self.value)

        def __str__(self):
            return str(self.value) + "; "

    def __init__(self, initial=None):
        self.front = self.back = self.current = None

    def empty(self):
        return self.front == self.back == None

    def __iter__(self):
        self.current = self.front
        return self

    def __str__(self):
        string = 'List[ '
        curr_node = self.front

        while curr_node != None:
            string += str(curr_node)
            curr_node = curr_node.next()
        string += ']'

        return string

    def __repr__(self):
        nodes = []
        curr = self.front

        while curr:
            nodes.append(repr(curr))
            curr = curr.next
        return '[' +', '.join(nodes) + ']'

    def __next__(self):
        if self.current:
            tmp = self.current.value
            self.current = self.current.next
            return tmp
        else:
            raise StopIteration()

    def push_front(self, value):
        x = self.Node(value, self.front)

        if self.empty():
            self.front = self.back = x
        else:
            self.front = x

#you need to(at least) implement the following three methods

    def pop_front(self):      
        if self.empty():
            raise RuntimeError("Empty List")
        x = self.front.value
        self.front = self.front.next
        if not self.front:
            self.back = None
        return x

    def push_back(self, value):
        if self.empty():
            self.front = self.back = self.Node(value, None)
        else:
            x = self.Node(value, None)
            self.back.next = x
            self.back = x

    def pop_back(self):
        if self.empty():
            raise RuntimeError("Empty List")
        y = self.back.value
        if not self.front.next:
            self.front = self.back = None
        else:
            x = self.front
            while x.next is not self.back:
                x = x.next
            x.next = None
            self.back = x
        return y

class TestInitialization(unittest.TestCase):
    def test(self):
        linked_list = LinkedList(("one", 2, 3.141592))
        self.assertEqual(linked_list.pop_back(), "one")
        self.assertEqual(linked_list.pop_back(), 2)
        self.assertEqual(linked_list.pop_back(), 3.141592)

class TestStr(unittest.TestCase):
    def test(self):
        linked_list = LinkedList((1, 2, 3))
        self.assertEqual(linked_list.__str__(), '1, 2, 3')

class TestRepr(unittest.TestCase):
    def test(self):
        linked_list = LinkedList((1, 2, 3))
        self.assertEqual(linked_list.__repr__(), 'LinkedList((1, 2, 3))')


if '__main__' == __name__:
    unittest.main()

现在,代码已经完成,我将提供我在控制台中遇到的问题:

1) Error at TestInitialization. RuntimeError("Empty List")
2) Failure at TestRepr. AssertionError: '[]' != 'LinkedList((1, 2, 3))'
- []
+ LinkedList((1, 2, 3))
3) Failure at TestStr. AssertionError: 'List[ ]' != '1, 2, 3'
- List[ ]
+ 1, 2, 3

我不想打扰,但我想寻求任何建议或提示,以帮助我纠正我的两个失败并防止一个错误。那么,有什么方法可以用来尝试这样做吗?我将不胜感激。

要使 TestInitialization 正常工作,您的初始化函数必须提供

的链接
3.141592 -> 2 -> "one"

if init(...)ed with ("one", 2, 3.141592) - 你可以通过检查测试用例看到,它从后面弹出,你需要匹配提供的值。 您可以通过在 init:

中将每个推到前面来解决它
def __init__(self, initial=None):
    self.front = self.back = self.current = None
    for i in initial:
        self.push_front(i)  

# I find this counterintuitive, blame your teacher.

要使 TestStr 工作,您使用 (1,2,3) 初始化它并且必须提供 '(1,2,3)' 的输出 - 由于 __init__ 现在的工作方式,您需要将所有节点收集到一个列表中,然后 return 它反向连接(或从后到前遍历列表):

def __str__(self):
    elem = []
    curr_node = self.front

    while curr_node != None:
        elem.append(str(curr_node.value)) # collect node values, not the "7; " str  
        curr_node = curr_node.next()
    # join reversed list 
    return ', '.join(elem[::-1]) # need to reverse the list due to how __init__ works

要使 TestRepr 工作,您需要 __str__ 输出和 prefix/postfix 它与 'LinkedList((''))'

def __repr__(self):
    return 'LinkedList(('+ str(self) + '))'

我无法测试自己,因为 NameError: name 'unittest' is not defined