"Tuple comprehensions" and the star splat/unpack operator *
--------------------------------------------------
Hire the world's top talent on demand or became one of them at Toptal: https://topt.al/25cXVn
--------------------------------------------------
Music by Eric Matyas
https://www.soundimage.org
Track title: Ancient Construction
--
Chapters
00:00 &Quot;Tuple Comprehensions&Quot; And The Star Splat/Unpack Operator *
01:30 Accepted Answer Score 1
02:39 Thank you
--
Full question
https://stackoverflow.com/questions/4757...
--
Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...
--
Tags
#python #python3x #tuples #listcomprehension #generatorexpression
#avk47
    Hire the world's top talent on demand or became one of them at Toptal: https://topt.al/25cXVn
--------------------------------------------------
Music by Eric Matyas
https://www.soundimage.org
Track title: Ancient Construction
--
Chapters
00:00 &Quot;Tuple Comprehensions&Quot; And The Star Splat/Unpack Operator *
01:30 Accepted Answer Score 1
02:39 Thank you
--
Full question
https://stackoverflow.com/questions/4757...
--
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.