"Tuple comprehensions" and the star splat/unpack operator *
Become part of the top 3% of the developers by applying to Toptal https://topt.al/25cXVn
--
Music by Eric Matyas
https://www.soundimage.org
Track title: Ominous Technology Looping
--
Chapters
00:00 Question
01:54 Accepted answer (Score 1)
03:20 Thank you
--
Full question
https://stackoverflow.com/questions/4757...
Question links:
[Why is there no tuple comprehension in Python?
]: https://stackoverflow.com/questions/1694...
[comments of the accepted answer]: https://stackoverflow.com/questions/1694...
[a more recent answer]: https://stackoverflow.com/a/47476344/629...
Accepted answer links:
[BUILD_TUPLE_UNPACK]: https://docs.python.org/3/library/dis.ht...
--
Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...
--
Tags
#python #python3x #tuples #listcomprehension #generatorexpression
#avk47
--
Music by Eric Matyas
https://www.soundimage.org
Track title: Ominous Technology Looping
--
Chapters
00:00 Question
01:54 Accepted answer (Score 1)
03:20 Thank you
--
Full question
https://stackoverflow.com/questions/4757...
Question links:
[Why is there no tuple comprehension in Python?
]: https://stackoverflow.com/questions/1694...
[comments of the accepted answer]: https://stackoverflow.com/questions/1694...
[a more recent answer]: https://stackoverflow.com/a/47476344/629...
Accepted answer links:
[BUILD_TUPLE_UNPACK]: https://docs.python.org/3/library/dis.ht...
--
Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...
--
Tags
#python #python3x #tuples #listcomprehension #generatorexpression
#avk47
ACCEPTED ANSWER
Score 1
To me, it seems like the second example is also one where a generator object is created first. Is this correct?
Yes, you're correct, checkout the CPython bytecode:
>>> import dis
>>> dis.dis("*(thing for thing in thing),")
1 0 LOAD_CONST 0 (<code object <genexpr> at 0x7f56e9347ed0, file "<dis>", line 1>)
2 LOAD_CONST 1 ('<genexpr>')
4 MAKE_FUNCTION 0
6 LOAD_NAME 0 (thing)
8 GET_ITER
10 CALL_FUNCTION 1
12 BUILD_TUPLE_UNPACK 1
14 POP_TOP
16 LOAD_CONST 2 (None)
18 RETURN_VALUE
Is there any difference between these expressions in terms of what goes on behind the scenes? In terms of performance? I assume the first and third could have latency issues while the second could have memory issues (as is discussed in the linked comments).
My timings suggest the first 1 is slightly faster, presumably because the unpacking is more expensive via BUILD_TUPLE_UNPACK than the tuple() call:
>>> from timeit import timeit
>>> def f1(): tuple(thing for thing in range(100000))
...
>>> def f2(): *(thing for thing in range(100000)),
...
>>> timeit(lambda: f1(), number=100)
0.5535585517063737
>>> timeit(lambda: f2(), number=100)
0.6043887557461858
Comparing the first one and the last, which one is more pythonic?
The first one seems far more readable to me, and also will work across different Python versions.