“元组理解"和星号splat/unpack运算符* [英] "Tuple comprehensions" and the star splat/unpack operator *

查看:138
本文介绍了“元组理解"和星号splat/unpack运算符*的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚读了一个问题为什么Python中没有元组理解?

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 comprehensions". Instead, our current option is to use a generator expression and pass the resulting generator object to the tuple constructor:

tuple(thing for thing in things)

或者,我们可以使用列表理解来创建列表,然后将该列表传递给元组构造函数:

Alternatively, we can create a list using a list comprehension and then pass the list to the tuple constructor:

tuple([thing for thing in things])

最后,与接受的答案相反,最近的答案指出,元组理解确实是一回事( (自Python 3.5开始)使用以下语法:

Lastly and to the contrary of the accepted answer, a more recent answer stated that tuple comprehensions are indeed a thing (since Python 3.5) using the following syntax:

*(thing for thing in things),

  • 在我看来,第二个示例也是第一个创建生成器对象的示例.这样对吗?

    • To me, it seems like the second example is also one where a generator object is created first. Is this correct?

      这些表达之间在幕后发生了什么变化?在性能方面?我假设第一个和第三个可能有延迟问题,而第二个可能有内存问题(如链接的注释中所述).

      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).

      更新:

      不出所料,列表理解的速度确实要快得多.我不明白为什么第一个比第三个要快.有什么想法吗?

      As expected, the list comprehension is indeed much faster. I don't understand why the first one is faster than the third one however. Any thoughts?

      >>> from timeit import timeit
      
      >>> a = 'tuple(i for i in range(10000))'
      >>> b = 'tuple([i for i in range(10000)])'
      >>> c = '*(i for i in range(10000)),'
      
      >>> print('A:', timeit(a, number=1000000))
      >>> print('B:', timeit(b, number=1000000))
      >>> print('C:', timeit(c, number=1000000))
      
      A: 438.98362647295824
      B: 271.7554752581845
      C: 455.59842588083677
      

      推荐答案

      在我看来,第二个例子也是一个发电机 首先创建对象.这是正确的吗?

      To me, it seems like the second example is also one where a generator object is created first. Is this correct?

      是的,是的,请检查CPython字节码:

      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).

      我的时间建议前1个要快一些,大概是因为通过 BUILD_TUPLE_UNPACK 而不是tuple()调用:

      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
      

      比较第一个和最后一个,哪个更pythonic?

      Comparing the first one and the last, which one is more pythonic?

      第一个对我来说似乎更具可读性,并且可以在不同的Python版本中使用.

      The first one seems far more readable to me, and also will work across different Python versions.

      这篇关于“元组理解"和星号splat/unpack运算符*的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆