python中嵌套for循环中使用索引的推荐样式

python中嵌套for循环中使用索引的推荐样式,python,Python,考虑为循环嵌套一个C样式,如下所示: for i = 0; i < n; i++ { for j = i; j < n; j++ { do_something(); } } 但是枚举和范围的组合似乎不一致 鉴于 for i in range(len(some_iter)): for j in range(i, len(some_iter)): do_something() 看起来是一致的,但使用了范围(len(一些词)) 推

考虑为循环嵌套一个C样式,如下所示:

for i = 0; i < n; i++ {
    for j = i; j < n; j++ {
        do_something();
    }
}
但是
枚举
范围
的组合似乎不一致

鉴于

for i in range(len(some_iter)):
    for j in range(i, len(some_iter)):
        do_something()
看起来是一致的,但使用了
范围(len(一些词))


推荐的Python风格是什么?

我尽量使用itemList中的
项:
,而不是将
I
用作变量,将
I
用作迭代器

for i in some_iter:
    for j in some_iter[some_iter.index(i):-1]
        doSomething()

因此,for的第二个
循环将列表从当前项的索引一直切片到末尾。

如前所述,实际上没有对任何内容使用
i
j
,因此嵌套循环是无意义的;您可以将计算出的循环次数作为单个顶级循环

这就是说,它遵循了处理给定输入序列中所有唯一对的常见模式,并且:

在没有不必要的索引的情况下,是Pythonic等效于:

for i in range(len(some_iter)):
    for j in range(i, len(some_iter)):
        do_something(some_iter[i], some_iter[j])
如果您还需要索引,只需将其与
枚举
配对即可:

for (ix, x), (iy, y) in itertools.combinations_with_replacement(enumerate(some_iter), 2):
    do_something(ix, x, iy, y)

使用
itertools.compositions\u与\u replacement
(带或不带
enumerate
)将更有效、更通用:如果您依赖索引,您将输入限制为序列,因此任意iterables(
set
dict
、生成器表达式等)如果不先将它们转换为序列,则无法工作。使用Pythonic方法意味着您可以接受并使用任何有限iterable,而无需执行手动类型转换和索引。

只需使用
范围
,您在enumerate中没有使用iterable的实际值,或者至少,这是您在enumerate(某些iter)中使用i的
所暗示的,在这种情况下,您应该选择
range
。IOW:“应尽可能使用枚举”不是真的。当你想枚举某个东西时,应该使用它,无论是给你一个索引和值,还是仅仅在你得到值时计算迭代次数,例如,
page\u no,enumerate(page,1)
我完全同意@juanpa.arrivillaga的说法<代码>枚举
不应总是努力使用,尤其是以可读性和清晰性为代价。
range(len(…)
enumerate
有一些完美有效的用例,只是为了在迭代iterable时替换需要元素和索引的常见模式。我没有读过这本书,但我猜测“应该避免range(len(某物)),并且应该尽可能使用enumerate”有没有办法阻止人们在Python中编写C-in-range(len(some_iter)):item=some_iter[i]
而不是enumerate(some_iter)中的item(
):
但是range和enumerate是不同的,如果你需要一个范围而不是一个项目,就不需要enumerate。对于i,enumerate(some_iter)中的iter肯定是
不是做任何事情的方法。使用
索引
是在每个内部循环之前添加一个浪费的(对于非唯一输入不准确的)线性扫描;
枚举
-外部循环将免费为您提供索引。此外,使用
i
(或
j
)也不是一个好主意作为除索引变量以外的任何名称,因为编程传统仅用于此目的,因此将其用于实际值会产生误导。感谢反馈,我个人通常不使用I和j作为名称,我只是遵循海报的格式。我通常会给它一个有意义的名称。旁注:通常,大多数时候,当人们认为他们需要
范围(len(someseq))
,有一半的时间他们认为他们需要
枚举
,声称这是因为他们的用例太复杂了,他们真的只是不太了解
zip
函数和
itertools
模块;在这两个模块和列表理解之间,他们几乎涵盖了您需要的所有内容。在许多这样的例子中<代码>枚举
在这种情况下,可以通过简单的列表理解来解决问题,生成新的
列表
,而不是将索引分配给旧列表(例如,
枚举
)。
for i in range(len(some_iter)):
    for j in range(i, len(some_iter)):
        do_something(some_iter[i], some_iter[j])
for (ix, x), (iy, y) in itertools.combinations_with_replacement(enumerate(some_iter), 2):
    do_something(ix, x, iy, y)