“Tuple comprehensions” and the star splat/unpack operator *

前端 未结 1 1456
清酒与你
清酒与你 2021-02-10 06:38

I just read the question Why is there no tuple comprehension in Python?

In the comments of the accepted answer, it is stated that there are no true \"tuple comprehensio

相关标签:
1条回答
  • 2021-02-10 07:10

    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.

    0 讨论(0)
提交回复
热议问题