问题
I am implementing a graph manipulation script and I was puzzled with the following error:
Traceback (most recent call last):
File ".....py", line 12, in <module>
print(len(graph.predecessors(i)), len(graph.successors(i)))
>>TypeError: object of type 'dict_keyiterator' has no len()<<
This is the code:
import networkx as nx
graph = nx.DiGraph()
for i in range(10):
graph.add_node(i)
for i in range(9):
graph.add_edge(i, i+1)
for i in range(10):
print(len(graph.predecessors(i)), len(graph.successors(i)))
What is this dict_keyiterator and how to fix my code? Thanks!
回答1:
The issue was eventually fixable by converting the iterator to a list:
print(len(list(graph.predecessors(i))), len(list(graph.successors(i))))
As suggested by Yakym Pirozhenko suggested an alternative approach deemed faster so I checked:
def f1():
for i in range(10):
len(list(graph.predecessors(i)))
def f2():
for i in range(10):
sum(1 for _ in graph.predecessors(i))
print(timeit.timeit(f1, number=100000))
print(timeit.timeit(f2, number=100000))
And got:
0.529827729
0.652576311
Clearly, the len(list(...)) approach is faster here.
I was using: Python 3.7 on Windows 10.
After some searching I have found a question with a similar problem and a straightforward explanation here:
In 2.x
iter(some_dict)returns a dictionary-keyiterator (weird hyphen). In 3.x it's adict_keyiterator(normal underscore).
So it seems that direct use of iter(d) where d is a dict results in the object of type dict_keyiterator in Python 3. This is one of 3 iterators replacing Python 2: d.viewkeys(), d.viewitems(), and d.viewvalues():
The corresponding iterators returned by
iter()in 3.x aredict_keyiterator,dict_itemiterator, anddict_valueiterator.
来源:https://stackoverflow.com/questions/53584341/len-throws-with-dict-keyiterator-has-no-len-when-calculating-outgoing-and-in