python - 为什么列出 `my_list+[' foo' ]` faster than ` new_list = list(my_list); python 中的 new_list.append ('foo' )`?

标签 python performance list

在编写一些 Python 代码时,我偶然发现了一些令我惊讶的事情。我正在考虑两种复制列表的方法,然后向副本中添加一个元素:

# I thought this would be clean-looking but slow since it creates an extra one element list, ['foo']
mylist = range(4)
newlist_0 = mylist + ['foo']
print newlist_0 # [0, 1, 2, 3, 'foo']

# I thought this would be faster
newlist_1 = list(mylist)
newlist_1.append('foo')
print newlist_1 # [0, 1, 2, 3, 'foo']

令人惊讶的是,第一种方法不仅美观而且速度更快。我跑了:

import timeit
for stmt in ['newlist_0 = mylist + ["foo"]', 'newlist_1 = list(mylist); newlist_1.append("foo")']:
    print "For statement {:50} timeit results are {}".format(stmt, timeit.repeat(setup='mylist = range(4)', stmt=stmt))

并得到这个输出:

For statement newlist_0 = mylist + ["foo"]                       timeit results are [0.29012012481689453, 0.3021109104156494, 0.32175779342651367]
For statement newlist_1 = list(mylist); newlist_1.append("foo")  timeit results are [0.39945101737976074, 0.39692091941833496, 0.38529205322265625]

突然我偶然发现了this question讨论 list(lst) 复制列表比 lst[:] 慢的事实,但切换到使用 [:] 复制mylist 不会改变任何东西。

最佳答案

我们来看看反汇编。您的第一个方法在 Python 2.7 字节码中如下所示:

          0 LOAD_FAST                0 (mylist)
          3 LOAD_CONST               1 ('foo')
          6 BUILD_LIST               1
          9 BINARY_ADD          

第二种方法如下所示:

          0 LOAD_GLOBAL              0 (list)
          3 LOAD_FAST                0 (mylist)
          6 CALL_FUNCTION            1
          9 STORE_FAST               1 (newlist_1)

         12 LOAD_FAST                1 (newlist_1)
         15 LOAD_ATTR                1 (append)
         18 LOAD_CONST               1 ('foo')
         21 CALL_FUNCTION            1

根据反汇编的比较,一些会使后者变慢的事情:

  1. list 必须从全局命名空间加载。

  2. append 必须从列表对象加载。

  3. 您支付两次调用开销,而不是一次。

简短的回答是,Python 字节码有非常简洁有效的方法来存储 ['foo'] 等短列表并执行二进制操作。

关于python - 为什么列出 `my_list+[' foo' ]` faster than ` new_list = list(my_list); python 中的 new_list.append ('foo' )`?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25610983/

相关文章:

python - 比较 Pandas 中两个不同的行和列数据框

performance - Corona SDK,加快声音播放

java - Java 应用程序的 CPU 使用率与处理器相关吗

python - 根据函数的输入交错列表

java - 使用 java 8 在列表中添加对象

python - 访问 xrange 内部结构

python - 根据第二列的值选择 csv 中的项目

java - 我怎样才能告诉python使用64位java?

c# - 不可变字典、字典、C5

java - 链表删除方法