4

Considering the following python session (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>

Nothing is unexpected here. Now, with 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 seems to interfer with islice behavior in a very unexpected way.

What is the rationale behind this behavior ? Is this because islice do not handle keyword arguments, like str.split few versions ago ?

aluriak
  • 5,559
  • 2
  • 26
  • 39

2 Answers2

4

Positional arguments are passed on after other positional arguments. So partial(islice, 0, 1)(l) is the same thing as islice(0, 1, l), which is not going to work.

You can't use a partial to pass in arguments in a different order; only keyword arguments would allow that. Since islice takes no keyword arguments, you can't use partial() here.

Your only option is to use a lambda.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
1

The problem is that doing:

partial(islice, 0, 1)

Translates to:

islice(0, 1, l)

Which fails because islice expects its arguments in a specific order. Using partial this way however causes the arguments to be passed in the wrong order. You can see this yourself if you pass a dummy function to 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])

And because you can't use keyword arguments with islice to change the order the arguments are passed, you can't use partial here. As @Martijn Pieters said, just use a normal function or 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]
Christian Dean
  • 22,138
  • 7
  • 54
  • 87