跳到内容

针对首个元素的不必要的可迭代对象分配 (RUF015)

修复总是可用的。

作用

检查以下构造,所有这些构造都可以用 next(iter(...)) 替换

  • list(...)[0]
  • tuple(...)[0]
  • list(i for i in ...)[0]
  • [i for i in ...][0]
  • list(...).pop(0)

为什么这不好?

调用例如 list(...) 将创建一个包含整个集合的新列表,这对于大型集合来说可能非常昂贵。如果您只需要集合的第一个元素,则可以使用 next(...)next(iter(...) 来惰性地获取第一个元素。其他构造也是如此。

示例

head = list(x)[0]
head = [x * x for x in range(10)][0]

建议改为

head = next(iter(x))
head = next(x * x for x in range(10))

修复安全性

此规则的修复被标记为不安全,因为从(例如)list(...)[0] 迁移到 next(iter(...)) 可能会以两种方式更改程序的行为

  1. 首先,上述所有构造都将急切地评估整个集合,而 next(iter(...)) 将只评估第一个元素。因此,在迭代过程中发生的任何副作用都将被延迟。
  2. 其次,通过方括号表示法 [0]pop() 函数访问集合的成员,如果集合为空,将引发 IndexError,而 next(iter(...)) 将引发 StopIteration

参考