下面的代码片段是否会创建并销毁每个循环上的常量列表,这会产生这意味着什么(尽管很小),或者列表是否创建过一次?

for i in <some-type-of-iterable>:
    if i in [1,3,5,18,3457,40567]:
        print(i)

我问的是Python“标准”,例如存在的,以及常见的CPython实现。
我知道这个例子是人为的,并且试图用CPython担心性能是愚蠢的,但我只是好奇。

===============>>#1 票数:3

这取决于python实现和版本以及如何使用“常量列表”。 在您的示例的Cpython2.7.10上,看起来答案是if语句的条件中的列表仅创建一次...

>>> def foo():
...   for i in iterable:
...     if i in [1, 3, 5]:
...       print(i)
... 
>>> import dis
>>> dis.dis(foo)
  2           0 SETUP_LOOP              34 (to 37)
              3 LOAD_GLOBAL              0 (iterable)
              6 GET_ITER            
        >>    7 FOR_ITER                26 (to 36)
             10 STORE_FAST               0 (i)

  3          13 LOAD_FAST                0 (i)
             16 LOAD_CONST               4 ((1, 3, 5))
             19 COMPARE_OP               6 (in)
             22 POP_JUMP_IF_FALSE        7

  4          25 LOAD_FAST                0 (i)
             28 PRINT_ITEM          
             29 PRINT_NEWLINE       
             30 JUMP_ABSOLUTE            7
             33 JUMP_ABSOLUTE            7
        >>   36 POP_BLOCK           
        >>   37 LOAD_CONST               0 (None)
             40 RETURN_VALUE        

注意: 16 LOAD_CONST 4 ((1, 3, 5))

Python的窥孔优化器已将我们的列表转换为元组(感谢python!)并将其存储为常量。 请注意,窥孔优化器只能在对象上执行这些变换,如果它知道您作为程序员绝对无法获得对列表的引用(否则,您可以改变列表并更改代码的含义)。 据我所知,他们只对list进行优化, set由完全常量组成的文字,并且是in运算符的RHS。 可能还有其他我不了解的情况( dis.dis是您找到这些优化的朋友)。

我在上面暗示了它,但你可以在更新版本的python中使用set-literals做同样的事情(在python3.2 +中, set被转换为常量frozenset )。 这样做的好处是set / frozenset平均成员资格测试速度比list / tuple快。

===============>>#2 票数:2 已采纳

使用Python 3.5的另一个示例, 为每次迭代创建列表。

>>> import dis
>>> def func():
...  for i in iterable:
...   for j in [1,2,3]:
...    print(i+j)
... 
>>> dis.dis(func)
  2           0 SETUP_LOOP              54 (to 57)
              3 LOAD_GLOBAL              0 (iterable)
              6 GET_ITER
        >>    7 FOR_ITER                46 (to 56)
             10 STORE_FAST               0 (i)

  3          13 SETUP_LOOP              37 (to 53)     
             16 LOAD_CONST               1 (1)        # building list
             19 LOAD_CONST               2 (2)
             22 LOAD_CONST               3 (3)
             25 BUILD_LIST               3
             28 GET_ITER
        >>   29 FOR_ITER                20 (to 52)    # inner loop body begin
             32 STORE_FAST               1 (j)

  4          35 LOAD_GLOBAL              1 (print)
             38 LOAD_FAST                0 (i)
             41 LOAD_FAST                1 (j)
             44 BINARY_ADD
             45 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
             48 POP_TOP
             49 JUMP_ABSOLUTE           29            # inner loop body end
        >>   52 POP_BLOCK
        >>   53 JUMP_ABSOLUTE            7            # outer loop end,
                                              # jumping back before list creation
        >>   56 POP_BLOCK
        >>   57 LOAD_CONST               0 (None)
             60 RETURN_VALUE

  ask by Baruch translate from so

未解决问题?本站智能推荐: