在 Python 中,创建列表有两种写法:
python
代码解读
复制代码
# 写法一:使用一对方括号
list_1 = []
# 写法二:调用 list()
list_2 = list()
那么哪种写法更好呢?
单从写法上来看,[]
要比 list()
简洁,那在性能和功能方面,二者又有怎样的差异呢?
使用 []
创建列表的速度比使用 list()
快
我们先使用 timeit
来测量一下这两种写法创建 100 万次空列表所花费的时间。timeit
是 Python 标准库中的一个模块,常用于测量小段代码的执行时间,非常适合性能测试和比较不同实现的效率。
python
代码解读
复制代码
import timeit
time_list = timeit.timeit('list()', number=1000000)
time_brackets = timeit.timeit('[]', number=1000000)
print(f"list()的耗时: {time_list} 秒")
print(f"[]的耗时: {time_brackets} 秒")
# list()的耗时: 0.04899674400803633 秒
# []的耗时: 0.02433863200712949 秒
我们发现使用 []
创建列表的速度比使用 list()
快。那为什么前者的速度更快呢?
我们可以借助 dis
模块,从这两种写法对应的字节码上看一看差别。dis.dis()
函数可以反汇编一段 Python 代码,显示它的字节码指令,以帮助开发者了解 Python 代码在底层是如何执行的。
python
代码解读
复制代码
import dis # pip3 install dis
print("Disassembly of create_list_with_list:")
dis.dis('list()')
print("Disassembly of create_list_with_brackets:")
dis.dis('[]')
这段脚本的运行结果如下:
vbnet
代码解读
复制代码
Disassembly of create_list_with_list:
0 0 RESUME 0
1 2 PUSH_NULL
4 LOAD_NAME 0 (list)
6 CALL 0
14 RETURN_VALUE
Disassembly of create_list_with_brackets:
0 0 RESUME 0
1 2 BUILD_LIST 0
4 RETURN_VALUE
由此不难发现,[]
和 list()
执行速度上的差异主要是因为执行的字节码指令不同。
[]
是一个直接生成列表的字面量(literal),只使用 BUILD_LIST
指令即可生成一个空列表。而 list()
是一个生成列表的函数,它需要先使用 LOAD_NAME
指令加载函数,然后通过 CALL
指令调用该函数。这个额外的步骤带来的开销就导致这种写法要比 []
慢。
除了 dis
模块,也可通过 godbolt.org/z/T39KesbPf 这个网站来对比这两种写法的差别:
二者在功能上的差异
[]
和 list()
都能创建空的列表,但在创建含有元素的列表时,二者的用法有所不同。
list()
可以接受一个(且只能是一个)可迭代对象作为参数,并将其转换为列表:
python
代码解读
复制代码
# 从可迭代对象创建列表
list_from_tuple = list((1, 2, 3)) # [1, 2, 3]
list_from_string = list("hello") # ['h', 'e', 'l', 'l', 'o']
list_from_dict_keys = list({"a": 1, "b": 2}.keys()) # ['a', 'b']
而在使用 []
创建非空列表时,需要一一列举出其中的元素:
python
代码解读
复制代码
list_nums = [1, 2, 3]
list_letters = ["a", "b", "c", "d"]
[]
不能直接将可迭代对象转换为列表。
综上所述,当需要创建一个空列表时,[]
是更简洁和高效的选择。而当需要将可迭代对象转换为列表时,就需要使用 list()
了。