Search code examples
python-3.xclasstreerepr

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


I have an error while debugging the following code by figuring out the usage of __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

Whenever I put the print(tree), there is an error, but if I commented this line, no error. If I change self.children.append**(nod)** to self.children.append**(node(nod))**, no error while I use 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

Question:

  1. why did I get the error? where can I see the 1 argument?
  2. why it must be using the self.children.append**(node(nod))**? I totally do not understand the logic behind it?

I have debugged and watched values, but I can only see the variables' updates and relations, I cannot see the reasons. I much appreciate it if anyone can explain a little bit to me, thanks!


Solution

  • Here's my attempt at answering your question:

    Your first error:

    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
    

    This is because in your class, you've defined the following:

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

    The level=0 represents a kwarg argument. If you need to use that argument, you need to do the following: ret += child.__repr__(level=level+1)

    If you had wanted just to do ret += child.__repr__(level+1), your __repr__ definition should be:

    def __repr__(self, level):
    

    Then calling ret += child.__repr__(level+1) would not give an error.

    Now, as for your other question on self.children.append**(node(nod))**;

    As stated in your code, leaf_* are lists.

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

    Your def add(self, nod): method just appends the value of nod to the self.children list. However, after all that appending, self.children would be just a list of lists, not a list of nodes which is what your expecting when you do the following:

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

    Since you defined the Node object's repr method, the above would be valid if each child were of a Node object; but they aren't.

    This is why when you do a self.children.append(Node(nod)), you are actually appending instantiated objects of Node type to the self.children field.

    So all in all, the final result should be:

    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)
    

    or you can, of course do what you did before:

    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)