Repository: networkx/networkx

Issue:
len(G.edges) unexpected values
I'm not sure if this is a bug or expected behavior but it's at least confusing.  This is using 2.0 nx.Graph() - I would provide the data to recreate, but it's private and I'm not sure why this is occurring, which might just be my lack of knowledge
```
>>> len(G.edges())
300
>>> G.number_of_edges()
312
>>> count = 0
>>> s = set()
>>> for edge in G.edges():
...     seen = edge in s or (edge[1], edge[0]) in s
...     if not seen:
...         count += 1
...     s.add(edge)
>>> count
312
```
What would be likely reasons that len() would give a different answer than number_of_edges()?  I thought it was because of reversed edges, but that doesn't seem to be the case either.

Discussion:

Patch:
diff --git a/networkx/classes/reportviews.py b/networkx/classes/reportviews.py
index ac5255f2f..6fe61f28f 100644
--- a/networkx/classes/reportviews.py
+++ b/networkx/classes/reportviews.py
@@ -791,8 +791,7 @@ class OutMultiEdgeDataView(OutEdgeDataView):
                         if data in dd else (n, nbr, default)
 
     def __len__(self):
-        return sum(len(kd) for n, nbrs in self._nodes_nbrs()
-                   for nbr, kd in nbrs.items())
+        return sum(1 for e in self)
 
     def __iter__(self):
         return (self._report(n, nbr, k, dd) for n, nbrs in self._nodes_nbrs()
@@ -821,10 +820,6 @@ class MultiEdgeDataView(OutMultiEdgeDataView):
     """An EdgeDataView class for edges of MultiGraph; See EdgeDataView"""
     __slots__ = ()
 
-    def __len__(self):
-        # nbunch makes it hard to count edges between nodes in nbunch
-        return sum(1 for e in self)
-
     def __iter__(self):
         seen = {}
         for n, nbrs in self._nodes_nbrs():
@@ -1016,7 +1011,7 @@ class EdgeView(OutEdgeView):
     dataview = EdgeDataView
 
     def __len__(self):
-        return sum(len(nbrs) for n, nbrs in self._nodes_nbrs()) // 2
+        return sum(len(nbrs) + (n in nbrs) for n, nbrs in self._nodes_nbrs()) // 2
 
     def __iter__(self):
         seen = {}
@@ -1120,8 +1115,7 @@ class MultiEdgeView(OutMultiEdgeView):
     dataview = MultiEdgeDataView
 
     def __len__(self):
-        return sum(len(kdict) for n, nbrs in self._nodes_nbrs()
-                   for nbr, kdict in nbrs.items()) // 2
+        return sum(1 for e in self)
 
     def __iter__(self):
         seen = {}


Test patch:
diff --git a/networkx/classes/tests/test_reportviews.py b/networkx/classes/tests/test_reportviews.py
index a4a5c2c1a..7fd96d4dd 100644
--- a/networkx/classes/tests/test_reportviews.py
+++ b/networkx/classes/tests/test_reportviews.py
@@ -326,6 +326,12 @@ class TestEdgeDataView(object):
         assert_equal(len(self.G.edges()), 8)
         assert_equal(len(self.G.edges), 8)
 
+        H = self.G.copy()
+        H.add_edge(1, 1)
+        assert_equal(len(H.edges(1)), 3)
+        assert_equal(len(H.edges()), 9)
+        assert_equal(len(H.edges), 9)
+
 
 class TestOutEdgeDataView(TestEdgeDataView):
     def setUp(self):
@@ -351,6 +357,12 @@ class TestOutEdgeDataView(TestEdgeDataView):
         assert_equal(len(self.G.edges()), 8)
         assert_equal(len(self.G.edges), 8)
 
+        H = self.G.copy()
+        H.add_edge(1, 1)
+        assert_equal(len(H.edges(1)), 2)
+        assert_equal(len(H.edges()), 9)
+        assert_equal(len(H.edges), 9)
+
 
 class TestInEdgeDataView(TestOutEdgeDataView):
     def setUp(self):
@@ -486,6 +498,12 @@ class TestEdgeView(object):
         num_ed = 9 if self.G.is_multigraph() else 8
         assert_equal(len(ev), num_ed)
 
+        H = self.G.copy()
+        H.add_edge(1, 1)
+        assert_equal(len(H.edges(1)), 3 + H.is_multigraph() - H.is_directed())
+        assert_equal(len(H.edges()), num_ed + 1)
+        assert_equal(len(H.edges), num_ed + 1)
+
     def test_and(self):
         # print("G & H edges:", gnv & hnv)
         ev = self.eview(self.G)