detaching comprehensions
Peter Otten
__peter__ at web.de
Fri Sep 8 17:03:47 EDT 2017
Stefan Ram wrote:
> Maybe you all know this, but to me this is something new.
> I learnt it by trial and error in the Python 3.6.0 console.
>
> Most will know list comprehensions:
>
> |>>> [ i for i in range( 3, 5 )]
> |[3, 4]
>
> I found out that the comprehension can be detached from the list:
>
> |>>> k =( i for i in range( 3, 5 ))
>
> but one must use an extra pair of parentheses around it in the
> assignment.
That is called "generator expression". When it does not modify the values
one usually creates the iterator with k = iter(range(3, 5)).
> Now I can insert the "generator" »k« into a function call,
> but a spread operator should cannot be used there.
>
> |>>> sum( k )
> |7
>
> »sum« expects exactly two arguments, and this is what »k«
> provides.
No. sum() requires one iterable and accepts an optional start value. You are
passing the iterable only, as may be verified with
>>> k = (x for x in [["a"], ["b"]])
>>> sum(k)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'list'
versus
>>> k = (x for x in [["a"], ["b"]])
>>> sum(k, [])
['a', 'b']
As with iterators in general once they are exhausted they stay exhausted:
>>> k = (i for i in range(3, 5))
>>> sum(k)
7
>>> sum(k)
0
(you can but shouldn't make your own that doesn't follow that convention)
> But to insert it again into the place where it was "taken
> from", a spread operator is required!
>
> |>>> k =( i for i in range( 3, 5 ))
> |>>> [ *k ]
> |[3, 4]
I have not seen that, I think. The common way is probably
>>> list("foo")
['f', 'o', 'o']
rather than
>>> [*"foo"]
['f', 'o', 'o']
and
>>> tuple("bar")
('b', 'a', 'r')
rather than
>>> *"bar",
('b', 'a', 'r')
As demonstrated this works with arbitrary iterables, not just generator
expressions.
More information about the Python-list
mailing list