【问题标题】:How can I overload the __repr__ method to display all items in a linked list Stack?如何重载 __repr__ 方法以显示链表堆栈中的所有项目?
【发布时间】:2021-11-27 02:55:21
【问题描述】:

我已经创建了 Node 和 Stack 类,但我不知道如何在 Stack 类中显示 repr 以便能够打印当前在堆栈中的所有项目?我一直在尝试连接节点,但我不确定 Stack() 不允许像列表那样迭代是怎么回事?

堆栈正常工作,我只是不知道如何显示它的内容?

这是我的代码:

class Stack:
    class Node:
        def __init__(self, elem, next):
            self.elem = elem
            self.next = next
        
        def __repr__(self):
            return str(self.elem)
    
    def __init__(self):
        self._stack = None
        self._size  = 0
        
    
    def __repr__(self):
        # *Not sure how to implement this properly*
        s = ''
        for i in range(self._size):
            last = self._stack.elem
            s += (str(last))+ ', '
            self._stack.elem = self._stack.next
        return 
    
    def push(self, elem):
        if self._stack == None:
            self._stack = self.Node(elem, None)
            self._size += 1 
        else: 
            self._stack = self.Node(elem, self._stack)
            self._size += 1 
    
    def pop(self):
        if self._stack == None:
            raise Exception ('This Stack is empty!')
        else: 
            last = self._stack.elem
            self._stack = self._stack.next
            self._size -= 1
        return last
    
    def top(self):
        return  self._stack.elem
    
    def isEmpty(self):
        return self._size == 0

例子:

s= Stack()
s.push(4)
s.push(9)
s.push("joe")
s
joe, 9, 9, 

提前谢谢你。

【问题讨论】:

  • 我要注意的是,通常情况下,Python 类实例的repr 是您可以粘贴回解释器以重新创建等效实例的东西。如果你想生成一个规范的repr,你应该允许你的类通过传递一个可迭代的对象来构造,而不仅仅是创建一个空的并逐项填充。同样,您的Node repr 几乎肯定应该使用包含项目的repr,而不是str 形式(省略"Node()" 可以,因为Node 是一个实现细节)。
  • 您不应该在循环中使用实例变量,它们应该只是局部变量。实例变量用于对象的永久状态。
  • 我不认为调用_repr_ 应该改变堆栈。
  • 你需要把return改成return s
  • 在您当前的__repr__ 实现中,您实际上修改了self._stack.elem - 这是您不想要的副作用。此外,您不应该使用像 next 这样的名称,因为它们会影响 Python 内置的 next;此外,虽然您可以将堆栈实现为链表,但它并没有真正的好处,因此您可能应该只使用列表作为内部存储,甚至只使用现有的 Python 类来存储这种类型的功能。

标签: python python-3.x singly-linked-list


【解决方案1】:

一种更简单的实现方式,可以避免解决方案中的所有问题和陷阱:

from typing import Iterable, Any


class Stack:
    def __init__(self, xs: Iterable = None):
        self._items = [] if xs is None else list(xs)

    def push(self, elem: Any):
        self._items.append(elem)

    def pop(self) -> Any:
        return self._items.pop()

    def top(self) -> Any:
        return self._items[-1]

    def isEmpty(self) -> bool:
        return not self._items

    def __repr__(self) -> str:
        typename = type(self).__name__
        return f'{typename}({self._items})'

    def __str__(self) -> str:
        return ', '.join(str(x) for x in self._items)


s = Stack()
s.push(4)
s.push(9)
s.push("joe")
print(s)
print(repr(s))

但请注意,与仅使用像堆栈这样的列表相比,这样的类几乎没有用处。

输出:

4, 9, joe
Stack([4, 9, 'joe'])

请注意,这在末尾有顶部元素,当然,如果您愿意,可以将其反转。

如果您坚持使用 __repr__ 来实现您的特定实施,请按照您的意图以非标准方式使用 __repr__,这样的事情会起作用:

    def __repr__(self):
        p = self._stack
        elems = []
        while p is not None:
            elems.append(p.elem)
            p = p.next
        return ', '.join(elems)

但请注意,您的实现还有其他几个问题,除了这不是正确的__repr__,正如之前在此处和 cmets 中指出的那样。你的“节点”有一个__repr__,它只返回它的元素值(在大多数情况下这根本不是一个有效的表示);你似乎在使用__repr__,而你真正在使用__str__

如果这是编程课上的作业,我不确定我是否会获得及格分数,这取决于目标是什么。

【讨论】:

  • 为了额外的安全,装饰__repr__with @reprlib.recursive_repr(),所以如果你把一个堆栈推到它自己上,尝试显示它的repr不要死在无限递归的火焰中。您应该使用几乎任何通用集合来执行此操作(并且可以说对于实际上不是不可变内置类型的子类的任何用户定义类型,例如 inttuple 等,使用 __slots__ = (),因为可以想象,如果不明智的话,他们都可以控制自己)。
  • 是的,我同意使用列表对象会更简单。但为此,我尝试使用单链表来创建堆栈。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-19
  • 2020-10-30
  • 2022-01-25
  • 1970-01-01
  • 1970-01-01
  • 2023-04-03
相关资源
最近更新 更多