Graph Class: TypeError: __init__() takes 1 positional argument but 3 were given

Viewed 90
class _Edges(defaultdict):

    def __missing__(self, vertex):
        self.setdefault(vertex, True)

    def __delitem__(self, dst):
        self[dst] = False

    def del_vertex(self, dst):
        super().__delitem__(dst)

class Graph(defaultdict):

    def __init__(self):
        super().__init__(_Edges)
    
    def copy(self):
        return super().__copy__()

I'm trying to write a class that makes a graph but when I try to call the copy function I get the error. Should I write my own __copy__? I thought that I could use defaultdict's copy to copy the graph.

The copy class is supposed to create an exact copy of the graph by calling graph.copy() ex.

g = Graph() 
g['a']['b'] = 5
x = g.copy()

This would make an exact copy but i get the error stated above instead

1 Answers

Based on testing, I'm fairly sure that the __copy__ implementation of defaultdict will call __init__ on Graph with at least two arguments:

To address that, you could modify your Graph class to be:

class Graph(defaultdict):
  def __init__(self, *args):
    if len(args) == 0:
      super().__init__(_Edges)
    else:
      super().__init__(*args)

so if it is being called as part of a copying operation (when args contains a value), all the values are simply passed along to the defaultdict implementation; but if args is empty, the defaultdict implementation is called with only the default_factory argument. With this implementation, you may not need to provide a copy or __copy__, as defaulting to the one provided by defaultdict is sufficient.

Related