假设我有一个项目列表,我想遍历其中的前几个:
items = list(range(10)) # I mean this to represent any kind of iterable.
limit = 5
来自其他语言的Python naïf可能会编写这种完全可服务且性能良好(如果是单体的话)的代码:
index = 0
for item in items: # Python's `for` loop is a for-each.
print(item) # or whatever function of that item.
index += 1
if index == limit:
break
但是Python已经枚举了,它很好地包含了大约一半的代码:
for index, item in enumerate(items):
print(item)
if index == limit: # There's gotta be a better way.
break
所以我们要把额外的代码减半。但总有更好的办法。
如果enumerate采用了另一个可选的stop
参数(例如,它采用了这样的start
参数:enumerate(items, start=1)
),我认为这是理想的,但下面的参数不存在(请参见documentation on enumerate here):
# hypothetical code, not implemented:
for _, item in enumerate(items, start=0, stop=limit): # `stop` not implemented
print(item)
注意,不需要命名index
,因为不需要引用它。
有没有一种惯用的方法来写上面的东西?怎样?
第二个问题:为什么不将其内置到枚举中?
为什么不简单地使用
这只适用于一些iterable,但是由于您指定了列表,所以它可以工作。
如果你使用集合或听写等,它就不起作用
包括索引
zip
在其参数的最短iteable上停止。(与使用最长iterable的zip_longest
的行为相反。)range
可以提供一个有限的iterable,我们可以将它与主iterable一起传递给zip。因此,我们可以将
range
对象(带有stop
参数)传递给zip
,并像有限枚举一样使用它。zip(range(limit), items)
使用Python 3,
zip
和range
返回iterables,它通过管道传输数据,而不是在中间步骤的列表中具体化数据。要在Python 2中获得相同的行为,只需将
xrange
替换为range
,将itertools.izip
替换为zip
。如果不需要索引,
itertools.islice
您可以使用
itertools.islice
:它不需要分配给索引。
组合
enumerate(islice(items, stop))
以获取索引正如Pablo Ruiz Ruiz所指出的,我们也可以用枚举来组成岛。
下面是用纯Python实现的枚举(可能会进行修改以在注释中获得所需的行为):
对于那些已经使用枚举的人来说,上面的性能会降低,因为它必须检查是否是停止每个迭代的时间。如果没有stop参数,我们可以检查并使用旧的枚举:
这种额外的检查对性能的影响可以忽略不计。
至于为什么枚举没有stop参数,这是最初提出的(参见PEP 279):
显然
start
之所以被保留是因为它非常有价值,而stop
之所以被删除是因为它的用例较少,并且导致了对新函数使用的混淆。避免使用下标符号进行切片
另一个答案是:
这里有几个缺点:
只有在理解限制以及它是生成副本还是视图时,才应使用带下标符号的切片。
结论
我假设现在Python社区知道了枚举的用法,参数的值将超过混淆成本。
在此之前,您可以使用:
或者
或者,如果您根本不需要索引:
避免使用下标符号进行切片,除非您了解这些限制。
你可以用^{} 来做这个。它接受
start
、stop
和step
参数,如果只传递一个参数,则它被视为stop
。它将与任何iterable一起工作。演示:
文档示例:
相关问题 更多 >
编程相关推荐