Create a directed graph and compute in degrees in Python I have implemented a couple of functions in python as part of an online course. Although the functions seem to work fine I feel that the code is inefficient with a lot of nested loops. Are there any improvements I can make? I am new to the language so any advice is welcome.

Here is the code and some simple tests:

def make_complete_graph(num_nodes):
    """
    Takes the number of nodes num_nodes
    and returns a dictionary corresponding to a complete directed graph
    with the specified number of nodes
    """

    result = dict()
    for i in range(num_nodes):
        set_per_node = set()
        for num in range(num_nodes):
            if num != i:
                set_per_node.add(num)
        result[i] = set_per_node

    return result

def compute_in_degrees(digraph):
    """
    Takes a directed graph digraph (represented as a dictionary) and computes
    the in-degrees for the nodes in the graph.
    Returns a dictionary with the same set of keys (nodes) as digraph
    whose corresponding values are the number of edges
    whose head matches a particular node.
    """
    result = dict()
    count = 0
    for key in digraph:
        count = 0
        for key2, value in digraph.iteritems():
            if key != key2:
                for val in value:
                    if val == key:
                        count += 1
        result[key] = count
        count = 0

    return result


class TestStringMethods(unittest.TestCase):

    def test_make_complete_graph(self):
        expected_dict_one = {0: set([1, 2]), 1: set([0, 2]), 2: set([0, 1])}
        expected_dict_two = {}

        actual_dict_one = at_project1.make_complete_graph(3)
        actual_dict_two = at_project1.make_complete_graph(0)

        self.assertEquals(actual_dict_one, expected_dict_one)
        self.assertEquals(actual_dict_two, expected_dict_two)

    def test_compute_in_degrees(self):
        given_dict_one = {0: set([1, 2]), 1: set([0, 2]), 2: set([0, 1])}
        given_dict_two = {0: set([1, 2]), 1: set([]), 2: set([])}

        expected_dict_one = {0: 2, 1: 2, 2: 2}
        expected_dict_two = {0: 0, 1: 1, 2: 1}

        actual_dict_one = at_project1.compute_in_degrees(given_dict_one)
        actual_dict_two = at_project1.compute_in_degrees(given_dict_two)

        self.assertEquals(actual_dict_one, expected_dict_one)
        self.assertEquals(actual_dict_two, expected_dict_two)

if __name__ == '__main__':
    unittest.main()
In make_complete_graph, the inner loop could be written with a list comprehension:

result[i] = set([num for num in range(num_nodes) if num != i])


In compute_in_degrees, instead of iterating over all nodes for all nodes x to find links going to x, you could build a dictionary of counts easier:

counts = dict([(x, 0) for x in digraph])
for targets in digraph.values():
    for target in targets:
        counts[target] += 1