Python itertools.dropwhile的困难

Python itertools.dropwhile的困难,python,itertools,Python,Itertools,我正在尝试使用itertools.dropwhile仅从生成器返回第三个元素之后的元素,但我遇到了一些问题: from itertools import dropwhile it = (i for i in range(10,20)) a = dropwhile(enumerate < 3, it) next(a) TypeError: 'bool' object is not callable 有人能解释我的代码有什么问题并提供一个有效的解决方

我正在尝试使用
itertools.dropwhile
仅从生成器返回第三个元素之后的元素,但我遇到了一些问题:

from itertools import dropwhile

    it = (i for i in range(10,20))
    a = dropwhile(enumerate < 3, it)   
    next(a)
    TypeError: 'bool' object is not callable 
有人能解释我的代码有什么问题并提供一个有效的解决方案吗?谢谢。

试试:

a = dropwhile(lambda x:x < 3, it)  
a=dropwhile(λx:x<3,it)

参数必须是可调用的。

itertools
提供了一个函数,该函数完全可以执行您想要的功能,并且可以执行更多操作。从

itertools.
islice
(iterable[,start],stop[,step])

生成一个迭代器,从iterable返回选定的元素。如果start为非零,则将跳过iterable中的元素,直到到达start。之后,元素将连续返回,除非步骤设置高于导致跳过项的步骤。如果stop为
None
,则迭代将继续,直到迭代器耗尽(如果有);否则,它将停止在指定位置

导入itertools >>>它=(范围(10,20)内的i表示i)#它=范围(10,20) >>>a=itertools.islice(it,4,无) >>>名单(a) [14, 15, 16, 17, 18, 19]
itertools.drop的
谓词
参数
应该是一个接受单个参数的函数,
枚举<3
只是一个语句。在Python2.x上,这将始终计算为False,因为在Python3.x上,这将导致
类型错误:无序类型:type()

以下是如何更改代码并仍然使用dropwhile的方法:

>>> it = (i for i in range(10, 20))
>>> a = dropwhile(lambda i_v: i_v[0] < 4, enumerate(it))
>>> list(a)
[(4, 14), (5, 15), (6, 16), (7, 17), (8, 18), (9, 19)]
>>it=(范围(10,20)内的i代表i)
>>>a=dropwhile(lambda i_v:i_v[0]<4,枚举(it))
>>>名单(a)
[(4, 14), (5, 15), (6, 16), (7, 17), (8, 18), (9, 19)]
请注意,必须对iterable调用
枚举
,以便我们可以创建一个lambda,该lambda使用索引确定是否删除当前值,但这意味着结果是
(索引,值)
元组列表,而不仅仅是值。我还将比较改为
<4
,因为您希望从
14
开始,这是
it
的第四个元素

更好的选择是使用
itertools.islice
,如中所示

这有点多余,为什么不简单地使用
range(10,20)
(或者
xrange

您的代码中断是因为
dropwhile
需要一个函数作为其参数,而您提供的是一个布尔值(通过将函数
enumerate
与数字3进行比较,这有点奇怪!)

使用enumerate的解决方案可能如下所示:

a = dropwhile(lambda (i,val): i<3), enumerate(seq))
(在行动中看到它,它非常简单)

然后你可以像这样使用它:

c = Counter()
a = dropwhile(lambda elem: c() < 3, seq)

islice
允许您像列表切片一样进行切片(在本例中,类似于
myList[3://code>,从元素#3到结尾),但可以将任何序列作为其参数。

这里的一些其他答案很有帮助,但它们没有给出所需的确切结果。公认的答案解释了有用的
itertools.islice()。其他一些答案是不必要的复杂

一个简单的解决方案可能比预期的更容易找到。例如:

list(dropwhile(lambda x: x < 14, xrange(10, 20)))

但这还不包括使用
itertools.dropwhile()

的目标,因为
13
也会出现在输出中吗?
(范围(10,20)中的i代表i)是多余的。您可以按原样迭代
范围(10,20)
。是的,
dropwhile
正在比较项目的值。使用
islice
处理索引。dropwhile中函数的两个参数不起作用,在Python 2.x中,可以使用
lambda(i,val):…
但这是Python 3.x上的一个语法错误。我喜欢
计数器
方法,但可能会使用它,而不是创建一个新类。感谢您指出缺少paren,是的,我有点怀念py3中的tuple解包。感谢您也提到了
count
,尽管我只是建议使用计数器类进行说明,因为
islice
是这里的实际解决方案。谢谢,我没有想到使用
islice
。当然,最干净的解决方案。@turtle:
range(10,20)[4::
range(14,20)
更好。调用
list(result)
以获取Python 3上的列表。@J.F.Sebastian
islice
更便于移植,因为Python 2中不支持
xrange(10,20)[4://code>。我同意,仅在Python3中,您的
范围(10,20)[4://code>更好。@DeokhwanKim:OP的代码是Python2<代码>范围(10,20)[4://code>在Python2上工作(因为
range
返回一个列表)<代码>列表(范围(10,20)[4:])
适用于Python 3。但是我明白你的意思,如果你想得到一个迭代器,而不是序列。@J.F.Sebastian@turtle我对J.F.Sebastian最后的评论有点困惑。我的回答是基于这样的推测,即问题是如何从迭代器中获取其子迭代器,
(i代表范围(10,20))中的i
部分只是一个错误,在生成一个小代码片段时出现了这个错误。如果最终的目标只是从Python 2中的
range()
中获取它的子
列表,那么
dropwhile
islice
都是杀伤力过大的,列表切片绝对是一种方法,正如J.F.Sebastian所说。
class Counter:
    def __init__(self):
        self.n = 0

    def __call__(self):
        current = self.n
        self.n += 1
        return current
c = Counter()
a = dropwhile(lambda elem: c() < 3, seq)
import itertools
a = itertools.islice(range(10, 20), 3, None)
list(dropwhile(lambda x: x < 14, xrange(10, 20)))
range(14, 20)