与functools.partial一起使用时,itertools.islice会引发ValueError

时间:2017-08-19 22:38:20

标签: python valueerror

考虑以下python会话(3.6.1):

>>> from itertools import islice
>>> l = [i for i in range(10)]
>>> islice(l, 0, 1)
<itertools.islice object at 0x7f87c9293638>
>>> (lambda it: islice(it, 0, 1))(l)
<itertools.islice object at 0x7fe35ab40408>

这里没有任何意外。现在,使用functools.partial

>>> from functools import partial
>>> partial(islice, 0, 1)(l)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: Stop argument for islice() must be None or an integer: 0 <= x <= sys.maxsize.

partial似乎以非常意外的方式干扰islice行为。

这种行为背后的理由是什么?这是因为islice不处理关键字参数,like str.split few versions ago

2 个答案:

答案 0 :(得分:2)

在其他位置参数之后,传递位置参数。因此partial(islice, 0, 1)(l)islice(0, 1, l)相同,但不起作用。

您不能使用partial以不同的顺序传入参数;只有关键字参数才允许这样做。由于islice不带关键字参数,因此无法在此使用partial()

您唯一的选择是使用lambda

答案 1 :(得分:1)

问题在于:

partial(islice, 0, 1)

转换为:

islice(0, 1, l)

哪个失败,因为islice期望其参数按特定顺序排列。但是,以这种方式使用partial会导致参数以错误的顺序传递。如果将虚函数传递给partial

,您可以自己看到
>>> def func(*args):
    print('args:', args)


>>> partial(func, 0, 1)(l)
args: (0, 1, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

由于您无法使用islice的关键字参数来更改参数的传递顺序,因此您无法在此处使用partial。正如@Martijn Pieters所说,只需使用普通函数或lambda

>>> from itertools import islice
>>> from functools import partial
>>> 
>>> f = lambda l: islice(l, 0, 1)
>>> l = [i for i in range(10)]
>>> list(f(l))
[0]