如何不依赖len或消耗迭代器判断Python可迭代对象为空并优化图反转函数
判断空可迭代对象且不消耗迭代器的优雅方案
针对你要将函数参数限定为Mapping[Any, Iterable]的需求,核心问题是在不依赖len()、不消耗迭代器的前提下判断可迭代对象是否为空,同时还要保证后续能完整遍历所有元素。这里有个既优雅又高效的解决方案,利用迭代器的next()方法结合try-except块来实现:
核心思路
对于任意可迭代对象,我们可以先将其转为迭代器,尝试取出第一个元素:
- 如果取出失败(抛出
StopIteration),说明该可迭代对象为空; - 如果成功取出第一个元素,就将这个元素与剩余的迭代器重新组合成一个新的可迭代对象,这样后续遍历就能拿到所有元素,不会丢失数据。
修改后的完整代码
from typing import Mapping, Any, Iterable from collections import defaultdict def edge_reversed_graph(g: Mapping[Any, Iterable]): d = defaultdict(set) for src, dst_nodes in g.items(): it = iter(dst_nodes) try: first_dst = next(it) except StopIteration: # 处理空可迭代对象的情况,确保src被加入结果 if src not in d: d[src] = set() else: # 先处理第一个取出的元素 d[first_dst].add(src) # 遍历剩余的元素 for dst in it: d[dst].add(src) return d
验证示例
用你提供的测试用例验证,结果完全符合预期:
>>> graph = dict(a='c', b='cd', c='abd', e='') >>> assert edge_reversed_graph(graph) == {'c': {'a', 'b'}, 'd': {'c', 'b'}, 'a': {'c'}, 'b': {'c'}, 'e': set()}
方案优势
- 无依赖:不需要依赖
Sized接口,支持所有Iterable类型(包括生成器、迭代器、字符串、列表等); - 不消耗迭代器:仅取出第一个元素后又重新组合,保证后续遍历能拿到全部数据;
- 高效简洁:判断空的操作是O(1)时间复杂度,整体逻辑清晰,比标记变量的写法更易读维护。
内容的提问来源于stack exchange,提问作者thorwhalen
相关产品推荐
相关产品推荐

