在计算 networkx 中的传出和传入边时,len 抛出“dict_keyiterator”没有 len()

sop*_*ros 4 python networkx python-3.x

我正在实现一个图形操作脚本,但我对以下错误感到困惑:

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()<<
Run Code Online (Sandbox Code Playgroud)

这是代码:

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)))
Run Code Online (Sandbox Code Playgroud)

这是什么dict_keyiterator以及如何修复我的代码?谢谢!

sop*_*ros 5

该问题最终可以通过将迭代器转换为列表来解决:

print(len(list(graph.predecessors(i))), len(list(graph.successors(i))))
Run Code Online (Sandbox Code Playgroud)

Yakym Pirozhenko 提出了一种被认为更快的替代方法,所以我检查了:

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))
Run Code Online (Sandbox Code Playgroud)

并得到:

0.529827729
0.652576311
Run Code Online (Sandbox Code Playgroud)

显然,len(list(...))这里的方法更快。我使用的是:Windows 10 上的 Python 3.7。


经过一番搜索,我发现了一个有类似问题的问题这里有一个简单的解释:

在 2.x 中iter(some_dict)返回一个字典键迭代器(奇怪的连字符)。在 3.x 中它是一个dict_keyiterator(正常的下划线)。

如此看来,直接使用的iter(d),其中ddict在类型的对象结果dict_keyiterator在Python 3.这是3的一个迭代器替换的Python 2: ,d.viewkeys()d.viewitems()d.viewvalues()

通过返回的相应的迭代器iter()在3.x的是 dict_keyiteratordict_itemiteratordict_valueiterator

  • 您可以使用 `sum(1 for _ in graph.predecessors(i))` 而不是 `len` + `list` 来避免创建新副本。 (2认同)