【问题标题】:Difference between 'any' with generator-comprehension and comprehension without parentheses? [duplicate]带有生成器理解的“任何”和不带括号的理解之间的区别? [复制]
【发布时间】:2018-08-27 12:28:18
【问题描述】:

查看我的一些代码,我意识到我写的内容本质上是:'

if (any(predicate for predicate in list_of_predicates)):
    # do something

我预料到会出现这种语法错误,因为它缺少“()”或“[]”。于是我在ipython中试了一下:

没有括号:

In [33]: timeit.repeat('any(True for x in xrange(10))', repeat=10)
Out[33]: 
[0.502741813659668,
 0.49950194358825684,
 0.6626348495483398,
 0.5485308170318604,
 0.5268769264221191,
 0.6033108234405518,
 0.4647831916809082,
 0.45836901664733887,
 0.46139097213745117,
 0.4977281093597412]

生成器理解:

In [34]: timeit.repeat('any((True for x in xrange(10)))', repeat=10)
Out[34]: 
[0.7183680534362793,
 0.6293261051177979,
 0.5045809745788574,
 0.4723200798034668,
 0.4649538993835449,
 0.5164840221405029,
 0.5919051170349121,
 0.5790350437164307,
 0.594775915145874,
 0.5718569755554199]

加速:

In [52]: reg = timeit.repeat('any(True for x in xrange(10))', repeat=100)

In [53]: comp = timeit.repeat('any((True for x in xrange(10)))', repeat=100)

In [55]: avg(reg)
Out[55]: 0.5245428466796875

In [56]: avg(comp)
Out[56]: 0.5283565306663514

In [57]: stddev(reg)
Out[57]: 0.05609485659272963

In [58]: stddev(comp)
Out[58]: 0.058506353663056954

In [59]: reg[50]
Out[59]: 0.46748805046081543

In [60]: comp[50]
Out[60]: 0.5147180557250977

没有括号似乎有边际(可能是噪音)性能优势 - 增加测试它看起来更像噪音。 这些处理方式之间是否存在根本区别

【问题讨论】:

    标签: python-2.7


    【解决方案1】:

    这些表达式是等价的。性能差异是噪音。

    来自original genexp PEP

    如果一个函数调用有一个位置参数,它可以是一个没有额外括号的生成器表达式,但在所有其他情况下,你必须给它加上括号。

    查看反汇编,你可以看到它们编译成相同的字节码:

    >>> def f():
    ...     any(True for x in xrange(10))
    ...
    >>> def g():
    ...     any((True for x in xrange(10)))
    ...
    >>> dis.dis(f)
      2           0 LOAD_GLOBAL              0 (any)
                  3 LOAD_CONST               1 (<code object <genexpr> at 0000000002
    B46A30, file "<stdin>", line 2>)
                  6 MAKE_FUNCTION            0
                  9 LOAD_GLOBAL              1 (xrange)
                 12 LOAD_CONST               2 (10)
                 15 CALL_FUNCTION            1
                 18 GET_ITER
                 19 CALL_FUNCTION            1
                 22 CALL_FUNCTION            1
                 25 POP_TOP
                 26 LOAD_CONST               0 (None)
                 29 RETURN_VALUE
    >>> dis.dis(g)
      2           0 LOAD_GLOBAL              0 (any)
                  3 LOAD_CONST               1 (<code object <genexpr> at 0000000002
    BE0DB0, file "<stdin>", line 2>)
                  6 MAKE_FUNCTION            0
                  9 LOAD_GLOBAL              1 (xrange)
                 12 LOAD_CONST               2 (10)
                 15 CALL_FUNCTION            1
                 18 GET_ITER
                 19 CALL_FUNCTION            1
                 22 CALL_FUNCTION            1
                 25 POP_TOP
                 26 LOAD_CONST               0 (None)
                 29 RETURN_VALUE
    >>> f.__code__.co_consts
    (None, <code object <genexpr> at 0000000002B46A30, file "<stdin>", line 2>, 10)
    >>> dis.dis(f.__code__.co_consts[1])  # the genexp's code object in f
      2           0 LOAD_FAST                0 (.0)
            >>    3 FOR_ITER                11 (to 17)
                  6 STORE_FAST               1 (x)
                  9 LOAD_GLOBAL              0 (True)
                 12 YIELD_VALUE
                 13 POP_TOP
                 14 JUMP_ABSOLUTE            3
            >>   17 LOAD_CONST               0 (None)
                 20 RETURN_VALUE
    >>> dis.dis(g.__code__.co_consts[1])  # the genexp's code object in g
      2           0 LOAD_FAST                0 (.0)
            >>    3 FOR_ITER                11 (to 17)
                  6 STORE_FAST               1 (x)
                  9 LOAD_GLOBAL              0 (True)
                 12 YIELD_VALUE
                 13 POP_TOP
                 14 JUMP_ABSOLUTE            3
            >>   17 LOAD_CONST               0 (None)
                 20 RETURN_VALUE
    

    【讨论】:

      猜你喜欢
      • 2016-05-04
      • 2011-11-27
      • 2012-05-05
      • 1970-01-01
      • 1970-01-01
      • 2023-03-19
      • 2017-08-16
      • 1970-01-01
      相关资源
      最近更新 更多