重写 __repr__ 'TypeError-expected 0 arguments, got 1' 时出错

Error while rewriting __repr__ 'TypeError-expected 0 arguments, got 1'

我在通过弄清楚 __repr__.

的用法来调试以下代码时出错
class node(object):
    def __init__(self, value):
        self.value = value
        self.children = []
    def __repr__(self, level=0):
        ret = "\t"*level+repr(self.value)+"\n"
        for child in self.children:
            ret += child.__repr__(level+1)
        return ret
    def add(self, nod):
        self.children.append(nod)
leaf_1 = [1,4,3]
leaf_2 = [2,5,3]
leaf_3 = [4,4,3]
leaf_4 = [5,5,5]
tree = parent = node(leaf_1)
parent.add(leaf_2)
parent.add(leaf_3)
parent.add(leaf_4) 
print(tree) # no error without this line

每当我输入print(tree)时,就会出错,但如果我注释掉这一行,就不会出错。如果我将 self.children.append**(nod)** 更改为 self.children.append**(node(nod))**,则在使用 print(tree) 时不会出错。

Traceback (most recent call last):
  File "C:\Users....tree.py", line 30, in <module>
    print(tree)
  File "C:\Users....tree.py", line 9, in __repr__
    ret += child.__repr__(level+1)
TypeError: expected 0 arguments, got 1

问题:

  1. 为什么我会收到错误消息?我在哪里可以看到 1 参数?
  2. 为什么一定要使用self.children.append**(node(nod))**?我完全不明白背后的逻辑?

我已经调试和查看了值,但我只能看到变量的更新和关系,看不到原因。如果有人能给我解释一下,我将不胜感激,谢谢!

这是我尝试回答您的问题:

你的第一个错误:

Traceback (most recent call last):
  File "C:\Users....tree.py", line 30, in <module>
    print(tree)
  File "C:\Users....tree.py", line 9, in __repr__
    ret += child.__repr__(level+1)
TypeError: expected 0 arguments, got 1

这是因为在您的 class 中,您定义了以下内容:

def __repr__(self, level=0):
        ret = "\t"*level+repr(self.value)+"\n"
        for child in self.children:
            ret += child.__repr__(level+1)
        return ret

level=0 表示 kwarg 参数。如果您需要使用该参数,则需要执行以下操作: ret += child.__repr__(level=level+1)

如果您只想做 ret += child.__repr__(level+1),您的 __repr__ 定义应该是:

def __repr__(self, level):

然后调用ret += child.__repr__(level+1)就不会报错了。

现在,关于 self.children.append**(node(nod))**;

上的另一个问题

如您的代码所述,leaf_* 是列表。

leaf_1 = [1,4,3]
leaf_2 = [2,5,3]
leaf_3 = [4,4,3]
leaf_4 = [5,5,5]

您的 def add(self, nod): 方法只是将 nod 的值附加到 self.children 列表。然而,在所有追加之后,self.children 将只是一个列表列表,而不是您执行以下操作时所期望的节点列表:

        for child in self.children:
            ret += child.__repr__(level+1)

由于您定义了 Node 对象的 repr 方法,因此如果每个子对象都是 Node 对象,则上述方法有效;但他们不是。

这就是为什么当您执行 self.children.append(Node(nod)) 时,您实际上是将节点类型的实例化对象附加到 self.children 字段。

所以综上所述,最后的结果应该是:

class node(object):

    def __init__(self, value):
        self.value = value
        self.children = []

    def __repr__(self, level=0):
        ret = "\t"*level+repr(self.value)+"\n"
        for child in self.children:
            ret += child.__repr__(level=level+1)
        return ret

    def add(self, nod):
        self.children.append(nod)


leaf_1 = [1,4,3]
leaf_2 = [2,5,3]
leaf_3 = [4,4,3]
leaf_4 = [5,5,5]
tree = parent = node(leaf_1)
parent.add(node(leaf_2))
parent.add(node(leaf_3))
parent.add(node(leaf_4)) 
print(tree)

或者你也可以,当然可以像你之前那样做:

class node(object):

    def __init__(self, value):
        self.value = value
        self.children = []

    def __repr__(self, level=0):
        ret = "\t"*level+repr(self.value)+"\n"
        for child in self.children:
            ret += child.__repr__(level=level+1)
        return ret

    def add(self, nod):
        self.children.append(node(nod))


leaf_1 = [1,4,3]
leaf_2 = [2,5,3]
leaf_3 = [4,4,3]
leaf_4 = [5,5,5]
tree = parent = node(leaf_1)
parent.add(leaf_2)
parent.add(leaf_3)
parent.add(leaf_4)