正确使用range(),为啥pylint会抱怨:不迭代时引用了range built-in

Posted

技术标签:

【中文标题】正确使用range(),为啥pylint会抱怨:不迭代时引用了range built-in【英文标题】:Correct use of range(), why does pylint complain: range built-in referenced when not iterating正确使用range(),为什么pylint会抱怨:不迭代时引用了range built-in 【发布时间】:2019-07-26 17:58:23 【问题描述】:

使用 range() 代替列表可能非常方便且切中要害,但如果将 range() 分配给变量,pylint 会发出警告。 (范围内建非迭代)

范围对象类似于列表(具有长度、可以随机访问、可迭代等),那么是否存在此代码错误的情况?

from typing import *

def fn(a: Sequence[int]) -> None:
    for x in a:
        print(x)

r = range(10, 100)

fn(r)

编辑(添加):

这样做的一个动机是传递范围而不是到处传递(开始,结束)对

【问题讨论】:

没什么问题,只是不是很 Pythonic 能否请您详细说明一下?恕我直言,它简洁,利用语言和高效(与 ie tuple(range(10,100)) 相比)我什至可以(实际上,我认为它会更好)让 a 的类型为 Sequence[int] 而不是 Iterable 这里有些人比我更了解这一点,但我的感觉是您正在创建一个范围,然后创建一个函数来迭代它。为什么不在函数中创建它?范围的唯一用途是在迭代时。 @JoshFriedlander 什么不是 Python 的?在需要 range 对象的地方使用 range 对象是完全 Pythonic 的。我倾向于说,忽略 pylint。 @JoshFriedlander 不,range 是一个容器。它的用途不仅仅是迭代它。 【参考方案1】:

我认为 pylint 没有正确地证明这个警告是正确的。

official 文档中的理由

(在 Python 3 中返回一个迭代器)

适用于迭代器(如地图)但不适用于范围。

要轻松查看iterator 对象和non-iterator 对象之间的差异,您可以执行以下几行

r = range(5)
print(list(r)) # [0, 1, 2, 3, 4]
print(list(r)) # [0, 1, 2, 3, 4]
m = map(int, '01234')
print(list(m)) # [0, 1, 2, 3, 4]
print(list(m)) # []

iterator 消耗了元素。

但我认为这不是一个好的做法,因为您可能会想将其用作列表,在某些情况下可能会比较慢。

让我们举两个例子

r = range(500000)
l = list(r)

%%time
for i in range(200):
    for k in r:
        pass
# 6.7 sec on my computer

%%time
for i in range(200):
    for k in l:
        pass

# 4.5 sec on my computer

主要区别在于list 是加载到内存中的,迭代速度更快。

编辑:如果您正在寻找速度,您可能想要使用列表,否则您应该使用范围。

我今天早些时候在 pylint 上打开了一个issue,如果这值得拉请求,我会稍后处理

【讨论】:

不要试图变得困难或任何事情,但是“由于range 不消耗内存,您绝对应该避免将它们存储在变量中”.. 为什么?有趣的是,列表更快(我会猜到相反的情况,特别是如果实际访问的值)。其他,如果我们正在追逐内存负载 - 范围将是有益的.. range 确实 不返回迭代器 如果这是 pylint 中的理由,那么 pylint 是完全错误的。无论如何,像容器一样使用range 对象并没有错。是的,您正在用略少更快的迭代换取潜在的巨大内存节省(以及其他好东西,如恒定时间成员检查和切片) @ttyridal 这样我会说每次都动态定义它们会更好。但你可能是对的。我将编辑我的答案:) @juanpa.arrivillaga 我完全同意你的观点,更新

以上是关于正确使用range(),为啥pylint会抱怨:不迭代时引用了range built-in的主要内容,如果未能解决你的问题,请参考以下文章

Pylint 抱怨将字符串与带有“is”的文字进行比较 [重复]

为啥 Pylint 在元类定义的属性使用上出错?

Facebook 调试器:为啥抱怨 app_id 缺失

pytest 固定装置从外部范围重新定义名称 [pylint]

为啥 python Visual Studio 代码中没有显示 pylint 的错误曲线?

为啥即使我有评估数据的条件,打字稿也会抱怨类型?