'Return a list of selfloop edges.
A selfloop edge has the same node at both ends.
Parameters
data : bool, optional (default=False)
Return selfloop edges as two tuples (u, v) (data=False)
or three-tuples (u, v, datadict) (data=True)
or three-tuples (u, v, datavalue) (data=\'attrname\')
default : value, optional (default=None)
Value used for edges that dont have the requested attribute.
Only relevant if data is not True or False.
keys : bool, optional (default=False)
If True, return edge keys with each edge.
Returns
edgelist : list of edge tuples
A list of all selfloop edges.
See Also
nodes_with_selfloops, number_of_selfloops
Examples
>>> G = nx.MultiGraph()   # or MultiDiGraph
>>> G.add_edge(1, 1)
0
>>> G.add_edge(1, 2)
0
>>> list(G.selfloop_edges())
[(1, 1)]
>>> list(G.selfloop_edges(data=True))
[(1, 1, {})]
>>> list(G.selfloop_edges(keys=True))
[(1, 1, 0)]
>>> list(G.selfloop_edges(keys=True, data=True))
[(1, 1, 0, {})]'

def selfloop_edges(self, data=False, keys=False, default=None):

    if (data is True):
        if keys:
            return ((n, n, k, d) for (n, nbrs) in self._adj.items() if (n in nbrs) for (k, d) in nbrs[n].items())
        else:
            return ((n, n, d) for (n, nbrs) in self._adj.items() if (n in nbrs) for d in nbrs[n].values())
    elif (data is not False):
        if keys:
            return ((n, n, k, d.get(data, default)) for (n, nbrs) in self._adj.items() if (n in nbrs) for (k, d) in nbrs[n].items())
        else:
            return ((n, n, d.get(data, default)) for (n, nbrs) in self._adj.items() if (n in nbrs) for d in nbrs[n].values())
    elif keys:
        return ((n, n, k) for (n, nbrs) in self._adj.items() if (n in nbrs) for k in nbrs[n])
    else:
        return ((n, n) for (n, nbrs) in self._adj.items() if (n in nbrs) for d in nbrs[n].values())
