Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Alternative Constructors in Python

I'm playing with graphs and coded a mixin module for creating graphs. I want to have in it some alternative constructors. This is what I have:

class Graph(GraphDegree, GraphDegreePlot, GraphGeneration, object):
    def __init__(self):
        self.nodes = set([])
        self.edges = {}
    def get_nodes(self):
        """
        get nodes in graph
        """
        return self.nodes
    def get_number_of_nodes(self):
        """
        get number of nodes in the graph
        """
        return len(self.nodes)
    def get_edges(self):
        """
        get edges in graph
        """
        return self.edges
    def get_heads_in_edges(self):
        """
        get heads in edges present on the graph
        """
        return self.edges.values()
    def add_node(self, node):
        """
        add new node to graph
        """
        if node in self.get_nodes():
            raise ValueError('Duplicate Node')
        else:
            self.nodes.add(node)
            self.edges[node] = []
    def add_connection(self, edge):
        """
        adds edge to graph
        """
        origin = edge.get_origin()
        destination = edge.get_destination()
        if origin not in self.get_nodes() or destination not in self.get_nodes():
            raise ValueError('Nodes need to be in the graph')
        self.get_edges()[origin].append(destination)
        self.get_edges()[destination].append(origin)
    def get_children(self, node):
        """
        Returns the list of nodes node node is connected to
        """
        return self.get_edges()[node]

class GraphGeneration(object):
    @classmethod
    def gen_graph_from_text(cls, file):
        '''
        Generate a graph from a txt. Each line of the txt begins with the source node and then the destination nodes follow
        '''
        cls.__init__()
        file = open(file, 'r')
        for line in file:
            origin = line[0]
            destinations = line[1:-1]
            cls.add_node(origin)
            for destination in destinations:
                cls.add_node(destination)
                edge = Edge(origin, destination)
                cls.add_connection(edge)



graph = Graph.gen_graph_from_text(file)

I want that to return a graph where nodes and edges are generated from the file. The method I wrote doesn't work, I don't know if it even makes sense. What I want to do is inside that method to use the __init__ method of Graph, but then add edges and nodes from the file. I could just write an instance level method to do this, but I have other altertive initializers in mind.

Thanks !

like image 816
FranGoitia Avatar asked Jun 23 '15 18:06

FranGoitia


People also ask

What is alternative constructor in Python?

Python allows you to define class methods as well, using the @classmethod decorator and a special first argument cls . The main use of class methods is defining methods that return an instance of the class, but aren't using the same code as __init__() .

What is similar to a constructor in Python class?

In Python, the method the __init__() simulates the constructor of the class. This method is called when the class is instantiated. It accepts the self-keyword as a first argument which allows accessing the attributes or method of the class.

What are types of constructor in Python?

In Python, there are two different types of constructors. Non-parameterized Constructor: The constructors in Python which have no parametres present is known as a non parameterized constructor. Parameterized Constructor: A constructor that has a parametre pre defined is known as a parameterized constructor.

Can you have 2 constructors in Python?

Providing Multiple Constructors With @classmethod in Python. A powerful technique for providing multiple constructors in Python is to use @classmethod . This decorator allows you to turn a regular method into a class method. Unlike regular methods, class methods don't take the current instance, self , as an argument.


1 Answers

Inside of your alternate constructors, use cls to create the new instance of the class. Then, just use self like you normally would and return it at the end.

NOTE: cls is a reference to the class itself, not the instance like you're expecting. Replacing all occurrences of cls with self except for the instantiation should give you the result you want. E.g.,

@classmethod
def gen_graph_from_text(cls, file):
    self = cls()
    file = open(file, 'r')
    for line in file:
        origin = line[0]
        destinations = line[1:-1]
        self.add_node(origin)
        for destination in destinations:
            self.add_node(destination)
            edge = Edge(origin, destination)
            self.add_connection(edge)
    return self
like image 61
Uyghur Lives Matter Avatar answered Sep 22 '22 00:09

Uyghur Lives Matter