python中嵌套for循环中使用索引的推荐样式
考虑为循环嵌套一个C样式,如下所示: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(一些词)) 推
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)