python Set Comprehensions如何工作?

时间:2013-12-10 14:01:34

标签: python set generator set-comprehension

Q1 - 以下是set()generator expression的{​​{1}}? (或者它们是否相同?如果是,set comprehension& list理解也在生成器上对应的类型转换吗?)

dict

Q2 - 评估是否考虑重复值&然后应用my_set = {x for x in range(10)}

删除它们
set()

理解是否比常规dup_set = {x for x in [0, 1, 2, 0, 1, 2]} 循环更快地执行(速度方式)?

更新 - 我尝试使用for进行速度比较。我不确定我是否只是(公平)。

timeit

现在,使用一些条件

C:\>python -m timeit "s = set()" "for x in range(10):" "
  s.add(x)"
100000 loops, best of 3: 2.3 usec per loop

C:\>python -m timeit "s = {x for x in range(10)}"
1000000 loops, best of 3: 1.68 usec per loop

所以,有一些区别,是因为C:\>python -m timeit "s = set()" "for x in range(10):" " if x%2: s.add(x)" 100000 loops, best of 3: 2.27 usec per loop C:\>python -m timeit "s = {x for x in range(10) if x%2}" 1000000 loops, best of 3: 1.83 usec per loop 中的功能是硬编码的吗?

1 个答案:

答案 0 :(得分:7)

Q1:是,是的,是的,是的。或者至少他们表现得像这样。如果你看一下字节码,它会有点不同。让我们反汇编这段代码(Python 2.7):

def list_comp(l):
    return [x+1 for x in l]

def dict_comp(l):
    return {x+1:0 for x in l}

def set_comp(l):
    return {x+1 for x in l}

def generator(l):
    return (x+1 for x in l)

这就是你得到的:

Disassembly of list_comp:
  2           0 BUILD_LIST              0
              3 LOAD_FAST               0 (l)
              6 GET_ITER            
        >>    7 FOR_ITER               16 (to 26)
             10 STORE_FAST              1 (x)
             13 LOAD_FAST               1 (x)
             16 LOAD_CONST              1 (1)
             19 BINARY_ADD          
             20 LIST_APPEND             2
             23 JUMP_ABSOLUTE           7
        >>   26 RETURN_VALUE
Disassembly of dict_comp:
  5           0 LOAD_CONST              1 (<code object <dictcomp> at 029DEE30)
              3 MAKE_FUNCTION           0
              6 LOAD_FAST               0 (l)
              9 GET_ITER            
             10 CALL_FUNCTION           1
             13 RETURN_VALUE  
Disassembly of set_comp:
  8           0 LOAD_CONST              1 (<code object <setcomp> at 029DECC8)
              3 MAKE_FUNCTION           0
              6 LOAD_FAST               0 (l)
              9 GET_ITER            
             10 CALL_FUNCTION           1
             13 RETURN_VALUE  
Disassembly of generator:
 11           0 LOAD_CONST              1 (<code object <genexpr> at 02A8FD58)
              3 MAKE_FUNCTION           0
              6 LOAD_FAST               0 (l)
              9 GET_ITER            
             10 CALL_FUNCTION           1
             13 RETURN_VALUE                     

dict comprenhension,set comprehension和generator的字节码几乎不一样。它们都加载了一个代码对象(<dictcomp><setcomp><genexpr>),然后从中创建一个可调用的函数。列表理解是不同的,因为它生成对应于列表理解的字节码。这次它被解释,因此不是原生的。

Q2:它并不真正考虑重复值,因为它会使用您提供的列表创建理解。然后它用理解创建集合。

关于时间安排:列表/字典/设置理解往往比其他任何事情都要快。即使它们被解释,生成的字节码也会针对大多数情况进行优化,使用SET_ADDLIST_APPENDMAP_ADD等特殊字节码指令。